vue項目中解決 IOS + H5 滑動邊界橡皮筋彈性效果(解決思路)
問題:
最近遇到一個問題,我們在企業(yè)微信中的 H5 項目中需要用到table表格(支持懶加載 上劃加載數(shù)據(jù))。但是他們在鎖頭、鎖列的情況下,依舊會出現(xiàn)邊界橡皮筋效果。就會顯示的很奇怪。
什么是ios橡皮筋效果:
我們知道元素超出所給定的高度會出現(xiàn)滾動條 | 橫向的或縱向的,在ios手機上當在全局范圍或局部范圍出現(xiàn)滾動的地方時,滑動使?jié)L動到頭時還可以繼續(xù)拖拽出一段距離的空白,松開手時立刻回彈回去。雖不影響功能,但是操作有點別扭,感覺這個table表格滑動的時候像是飄著上面的,不是固定的。
嘗試思路:
針對這個問題我也嘗試了不同的方案都不盡人意;
1,首先想到先使用css解決,前后使用了絕對定位和固定定位來提高層級,發(fā)現(xiàn)問題依然存在;
2,然后是用css屬性&::-webkit-scrollbar { display: none;} 來隱藏滾動條 ,還是不行,
3,后面引入網(wǎng)上的inobounce插件還是不行。此插件會禁用頁面的touchmove事件,導致頁面無法進行滑動;
4,因為我用的是原生的table來布局的,難道是table標簽的問題,后面我又重新用div來實現(xiàn)table表格的布局,發(fā)現(xiàn)還是會出現(xiàn)橡皮筋效果,說明不是標簽的問題,是ios瀏覽器隱藏的特性;
解決方案:
最后我想到,既然我關(guān)不掉,那我自己完全控制滑動好了;原理是禁用掉頁面touchumove的默認的滑動效果,使用元素的scrollLeft 和scrollTop這兩個原生的可寫屬性,來進行元素的上下和左右移動;
這樣做的好處在于,我自己完全控制了拖拽滑動行為。壞處在于丟失了原生滑動的慣性滑動,看著沒那么絲滑了。不過這點也可以后續(xù)通過 JavaScript 來優(yōu)化(暫時還沒寫 ,寫出來的效果不太好,不絲滑)。
效果圖如下:
可以上下左右滑動,是固頂?shù)模蛏匣瑒訒r標題部分不會跟隨移動;
可以懶加載:當下滑到觸底時會向父元素傳遞一個事件告訴父組件該請求下一頁的數(shù)據(jù)了;
主要實現(xiàn)代碼如下:
表格組件部分代碼如下:tableStrick.vue;
data() { return { listEle: null, // dom元素 // 記錄坐標 touchX: "", touchY: "", // 滑動坐標 startX: 0, startY: 0, // 滑動方向 direction: "", }; } mounted() { /* 獲取dom元素 這里最好不要用原生的dom獲取方式 */ this.listEle = this.$refs.main; /* 自己實現(xiàn)滾動效果 不會出現(xiàn)滾動回彈問題 但是滾動不絲滑了且沒有慣性 */ this.listEle.addEventListener("touchstart", this.touchstart, false); this.listEle.addEventListener("touchmove", this.touchmove, false); this.listEle.addEventListener("touchend", this.touchend, false); }, methods:{ /* 修改 瀏覽器默認的滑動容器行為 */ // 1,手指接觸屏幕 touchstart(event) { this.touchX = event.changedTouches[0].clientX; this.touchY = event.changedTouches[0].clientY; // 獲取此刻手指的橫坐標startX和縱坐標startY this.startX = event.touches[0].pageX; this.startY = event.touches[0].pageY; }, // 2, 手指滑動的過程 touchmove(event) { event.preventDefault(); // 計算手指偏移量 const offsetX = event.changedTouches[0].clientX - this.touchX; const offsetY = event.changedTouches[0].clientY - this.touchY; // 觸摸的坐標 this.touchX = event.changedTouches[0].clientX; this.touchY = event.changedTouches[0].clientY; // 手指滑動的方向 let moveEndX = event.changedTouches[0].pageX; let moveEndY = event.changedTouches[0].pageY; let X = moveEndX - this.startX; let Y = moveEndY - this.startY; // 注意 上下移動只能是上劃或下劃 左右移動也是同理 if (Math.abs(X) > Math.abs(Y) && X > 0) { // 開始移動 console.log('我向右滑了) this.listEle.scrollLeft = this.listEle.scrollLeft - offsetX; this.direction = "right"; } else if (Math.abs(X) > Math.abs(Y) && X < 0) { console.log('我向左滑了) this.listEle.scrollLeft = this.listEle.scrollLeft - offsetX; this.direction = "left"; } else if (Math.abs(Y) > Math.abs(X) && Y > 0) { console.log('我向下滑了) this.listEle.scrollTop = this.listEle.scrollTop - offsetY; /* 設置滾動到底的處理 */ this.scrollBottom(event); this.direction = "bottom"; } else if (Math.abs(Y) > Math.abs(X) && Y < 0) { console.log('我向上滑了) this.listEle.scrollTop = this.listEle.scrollTop - offsetY; this.direction = "top"; /* 設置滾動到底的處理 */ this.scrollBottom(event); } else { this.direction = ""; } }, // 3,手指離開屏幕 touchend(event) { this.touchX = event.changedTouches[0].clientX; this.touchY = event.changedTouches[0].clientY; // TODO 此處可以進行優(yōu)化滾動的慣性 暫未實現(xiàn) }, // 監(jiān)聽滾動條 注意 scroll 可能是橫向滾動條 也可能是縱向滾動條 scrollBottom(event) { // 1,可視區(qū)域 let clientHeight = this.listEle.clientHeight; // 2,滾動文檔高度 let scrollHeight = this.listEle.scrollHeight; // 3,此處相等說明:沒有縱向滾動條 可能出現(xiàn)了橫向滾動條 所以要忽略 if (clientHeight == scrollHeight) { return; } // 4,已滾動的高度 let scrollTop = parseInt(this.listEle.scrollTop); // 這里 -2 是為了控制誤差 if (scrollTop + clientHeight >= scrollHeight - 2) { console.log("滾動到底了"); // 把事件傳出去 父元素開始請求下一頁的數(shù)據(jù) this.$emit("scrollBottom"); } }, }
上面代碼講解:
1,mounted里面獲取表格元素或父元素,然后監(jiān)聽手指點擊事件,移動事件,離開事件;
2,touchstart方法中記錄坐標,touchmove使用 event.preventDefault();禁用掉原先的滑動效果,自己通過this.listEle.scrollLeft和this.listEle.scrollTop來進行移動;
3,注意:下面的代碼的意思是先要計算滑動的方向,然后再進行向?qū)囊苿?,防止上下左右一起移動,導致移動時太過敏感導致表格一直抖動;
4,scrollBottom方法是懶加載的處理 ,如果需要的話可以加上;主要是判斷上下滑動時距離是否觸底,觸底就讓父組件請求數(shù)據(jù)。
最后注意:
最后需要注意的是需要使用了懶加載 :需要對父元素中的scrollBottom這個方法進行防抖設置,因為滑動到底部觸底時存在多次連續(xù)觸底的行為(比較靈敏),這樣會同時執(zhí)行多次scrollBottom這個方法;導致數(shù)據(jù)請求過多;
防抖可以使用lodash
庫里面的debounce
方法;
使用如下:在mounted中對scrollBottom進行防抖 ,也可以對實際請求接口的 自定義方法 進行防抖,
mounted(){ /* 設置接口防抖 */ this.scrollBottom= _.debounce(this.scrollBottom, 500); }
通過 JavaScript 來優(yōu)化滾動的慣性 ,這個如果小伙伴們有好的方法可以放到評論區(qū)里學習一下;
到此這篇關(guān)于vue項目中解決 IOS + H5 滑動邊界橡皮筋彈性效果的文章就介紹到這了,更多相關(guān) IOS + H5 滑動邊界橡皮筋彈性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue3中Provide?/?Inject的實現(xiàn)原理分享
provide和inject主要為高階插件/組件庫提供用例,這篇文章主要給大家介紹了關(guān)于Vue3中Provide?/?Inject的實現(xiàn)原理,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-02-02