前言
最近用ionic
來開發(fā)微信公眾號(hào)器紧,看好的就是ionic
有成熟的UI框架,不需要自己去定義UI控件掌腰,當(dāng)然微信也提供了自家的UI控件肮蛹,但是數(shù)量實(shí)在太少省核,不敢恭維赋咽。
因?yàn)橐恢庇玫氖?code>chrome調(diào)試開發(fā)的頁面冬耿,測試的時(shí)候也沒有發(fā)現(xiàn)什么問題,但是直到將代碼放上服務(wù)器爱咬,然后通過iPhone
手機(jī)的微信公眾號(hào)來訪問開發(fā)的網(wǎng)頁,在滑動(dòng)到頂部或者底部的時(shí)候蜂绎,重復(fù)上滑或者重復(fù)下滑,會(huì)導(dǎo)致頁面卡死怪瓶,需要2洗贰,3秒后才能恢復(fù)正常敛滋。瞬間奔潰绎晃,這是個(gè)什么玩意兒灵妨。在百度上查了一下資料原來是-webkit-overflow-scrolling:touch
引起的解阅,有前端開發(fā)經(jīng)驗(yàn)的人都知道货抄,這個(gè)屬性是給網(wǎng)頁在iOS
設(shè)備中呈現(xiàn)并滾動(dòng)的時(shí)候朱转,起到更加流暢的作用藤为,有一個(gè)回彈的效果分别,跟原生iOS
滑動(dòng)的效果一樣耘斩,沒想到反而給iOS
設(shè)備挖了這么大的一個(gè)坑括授,wtf....
分析
經(jīng)網(wǎng)上查找一些資料描述是Safari
會(huì)對(duì)使用-webkit-overflow-scrolling
的網(wǎng)頁,會(huì)創(chuàng)建一個(gè)UIScrollView
却邓,給要顯示的元素使用。具體可以參考這篇文章恢恼,文章的作者也是遇到這個(gè)問題,并且估計(jì)快被逼瘋了...
通過chrome
檢查元素可以看到在網(wǎng)頁編譯并且跑起來之后场斑,ionic
有生成了一個(gè)類名為“scroll-content”
的div
漏隐,這個(gè)div
就是使用了-webkit-overflow-scrolling:touch
,仔細(xì)查看了資料包括上面那篇文章挺据,說是可以通過給滾動(dòng)的元素的內(nèi)部加一個(gè)div元素扁耐,然后設(shè)置這個(gè)內(nèi)部的div的高度100%+1px
或100%+1%
可以解決产阱,有些人就說是通過修改z-index
,還有些人說是不要讓那個(gè)滾動(dòng)的元素有relative
或者absolute
這樣的css定位王暗。由于是在ionic
的框架上進(jìn)行開發(fā)的頁面瘫筐,查找了元素“scroll-content”
這個(gè)div確實(shí)有絕對(duì)定位策肝,剛開始很擔(dān)心是ionic
框架的問題,難道這次要翔拙毫,但是上面的方法全部試了個(gè)遍缀蹄,可以很負(fù)責(zé)任的告訴你缺前,沒有用悬襟,沒有用,沒有用脊岳,不論是ios
設(shè)備的微信瀏覽器逝段,safari
瀏覽器,QQ
瀏覽器割捅,UC
瀏覽器奶躯,都是會(huì)存在這個(gè)卡死的問題。
解決方案
想了好久亿驾,既然是-webkit-overflow-scrolling:touch
引起的嘹黔,那么不用這個(gè)屬性就行了嘛,但是不用這個(gè)屬性颊乘,頁面滑動(dòng)起來真的是還不如讓這個(gè)bug
留著参淹,那感覺就像你看了一部無聲的,黑白的乏悄,畫質(zhì)賊差的電影。接著往下思考恳不,既然是在頂部或者底部的時(shí)候會(huì)出現(xiàn)卡死檩小,那么不如通過touchstart
和touchmove
事件來判斷是否到達(dá)頂部或者底部筐付,然后移除-webkit-overflow-scrolling:touch
瓦戚,不滿足的時(shí)候就重新加上-webkit-overflow-scrolling:touch
,這樣就不會(huì)影響滑動(dòng)印衔,實(shí)際上也是有點(diǎn)效果了,可以滑動(dòng)一點(diǎn)點(diǎn)与帆,但是你瘋狂的滑動(dòng)鲤桥,還是會(huì)出現(xiàn)卡死。
當(dāng)然這種方案是不行的贮喧,所以最后還是通過判斷是否到達(dá)底部或者頂部添加event.preventDefault();
來解決谓形,在網(wǎng)上也有人
說這樣是可行的。
但是這邊還有一個(gè)需要注意的點(diǎn)就是,如果你的頁面有刷新和加載分頁翘贮,那么你就需要注意設(shè)置event.preventDefault()
的時(shí)機(jī)狸页。
如果有下拉刷新,那么在scrollTop為0的時(shí)候齿穗,就不能設(shè)置event.preventDefault();如果有加載分頁脖卖,那么你就需要直到滑動(dòng)到最后一頁的時(shí)候,才能設(shè)置event.preventDefault()十籍,否者你一加載更多,頁面立馬就卡死了盏筐。
下面是我代碼:
preventFreezeAtTopOrBottomForIOS(isGetRefresher,contenClassName){
if(this.isIOS()){
let contentEle = document.getElementsByClassName(contenClassName)[0];
let lastY = 0; // Needed in order to determine direction of scroll.
contentEle.getElementsByClassName("scroll-content")[0].addEventListener('touchstart', function(event) {
lastY = event.touches[0].clientY;
});
//獲取滾動(dòng)元素
let scrollEle = contentEle.getElementsByClassName("scroll-content")[0];
//先移除監(jiān)聽事件
scrollEle.removeEventListener('touchmove', function (event) {
event.preventDefault();
}, false);
//再添加監(jiān)聽事件
scrollEle.addEventListener('touchmove', function(event) {
let top = event.touches[0].clientY;
// Determine scroll position and direction.
let scrollTop = scrollEle.scrollTop;
// console.log("--scrollTop--" + scrollTop);
let scrollHeight = scrollEle.scrollHeight;
// console.log("--scrollHeight--" + scrollHeight);
let clientHeight = scrollEle.clientHeight;
// console.log("--clientHeight--" + clientHeight);
let direction = (lastY - top) < 0 ? "up" : "down";
// FIX IT!
if (scrollTop == 0 && direction == "up") {
console.log("--到頂部--");
// Prevent scrolling up when already at top as this introduces a freeze.
if(!isGetRefresher){//沒有頭部刷新的宿亡,需要設(shè)置防止頭部freeze
event.preventDefault();
}
} else if (scrollTop >= (scrollHeight - clientHeight) && direction == "down") {
// Prevent scrolling down when already at bottom as this also introduces a freeze.
event.preventDefault();
console.log("--到底部--");
}
lastY = top;
});
}
}
由于我是使用ionic
框架來開發(fā)的烈钞,所以我這邊實(shí)際上滾動(dòng)是“scroll-content”
這個(gè)div馒过,并且每一個(gè)頁面都有一個(gè)“scroll-content”
来累,所以你在獲取對(duì)應(yīng)的頁面對(duì)應(yīng)不同的“scroll-content”
的時(shí)候,可以通過給ion-content
設(shè)置class
來獲取其下面的元素“scroll-content”
领猾。
參數(shù)說明:
其中的contentClassName
就是各個(gè)頁面的ion-content
對(duì)應(yīng)的classname
,注意需自己給ion-content
設(shè)置唯一的classname
,isGetRefresher
就是判斷是否有下拉刷新袁翁,是boolean
類型粱胜,至于加載更多,你不需要限制冗恨,只需要我上面說的,加載到最后再調(diào)用上面那段代碼傲武。反正就是內(nèi)容高度一變化态兴,你就得重新設(shè)置。
總結(jié)
感覺這種方法是比較好的解決方法了绍撞。如果你有其他更好的方法可以告訴我(估計(jì)你也沒有??),被這個(gè)bug
折磨了很久,總算是消停了怪蔑,當(dāng)然還是希望官方可以解決這個(gè)bug
。