最近使用uniapp做一些小程序的功能;需要在列表項中左滑實現菜單功能,之前沒有什么經驗,所以參考網上的各種文章最終才實現的功能;這里記錄一下實現過程;
先看視圖頁面:
<scroll-view v-if="myCustomerList.length!=0" :style="'height:'+ height" scroll-y lower-threshold="30" @scrolltolower="LoadMoreMyCustomers"> <view v-for="(item,index) in myCustomerList" :key="index" class="touch-item" :class="item.IsTouchMove?'touch-move-active':''" :data-index="index" @touchstart="touchStartMyItem" @touchmove="touchMoveMyItem"> <view class="itemcontent"> ...... </view> <view class="itembtn" style="background-color: red;">刪除</view> </view> </scroll-view>
上邊的代碼就是列表的基本界面代碼,其中主要有幾個點需要注意:
1、IsTouchMove是判斷當前項已經左滑,在獲得到列表后首先要給每一項添加這個屬性默認值為false
2、touchstart和touchmove是拖動單個項的關鍵事件
3、class="touch-item"是單個項的樣式,需要注意的是touch-move-active樣式是當IsTouchMove時才需要設置的,否則不設置;
4、class="itemcontent"是內容樣式
5、class="itembtn"是左滑后顯示的菜單樣式
內容和菜單需要平級
下邊再看下樣式部分:
.touch-item { background-color: #F8F9FC; display: flex; justify-content: space-between; width: 100%; overflow: hidden } .itemcontent { display: flex; flex-direction: column; padding: 5px 10px; border-bottom: 1px solid #eeeeee; margin-right: 0; margin-left: -100px; width: 100%; -webkit-transition: all 0.4s; transition: all 0.4s; -webkit-transform: translateX(100px); transform: translateX(100px); position: relative; } .itembtn { width: 100px; display: flex; flex-direction: column; align-items: center; justify-content: center; background-color: #119bf8; color: white; position: relative; -webkit-transform: translateX(100px); transform: translateX(100px); -webkit-transition: all 0.4s; transition: all 0.4s; } .touch-move-active .itemcontent, .touch-move-active .itembtn { -webkit-transform: translateX(0); transform: translateX(0); }
樣式部分注意點:
1、需要設置單個項的寬度為100%,禁止滾動;
2、itemcontent的margin-left為負值,絕對值和itembtn的寬度要一致;並且itemcontent的寬度要默認為width: 100%,這樣才能默認占滿整行;
3、itemcontent和itembtn的translateX都是itembtn的寬度
最后看下實現邏輯:
touchStartMyItem(e) { this.myCustomerList.forEach(item => { if (item.IsTouchMove) { item.IsTouchMove = false; } this.startX = e.changedTouches[0].clientX; this.startY = e.changedTouches[0].clientY; }) }, touchMoveMyItem(e) { let that = this; let index = e.currentTarget.dataset.index; //當前索引 let startX = that.startX; //開始X坐標 let startY = that.startY; //開始Y坐標 let touchMoveX = e.changedTouches[0].clientX; //滑動變化坐標 let touchMoveY = e.changedTouches[0].clientY; //滑動變化坐標 //獲取滑動角度 let angle = that.angle({ X: startX, Y: startY }, { X: touchMoveX, Y: touchMoveY });
/滑動超過30度角 return
if (Math.abs(angle) > 30) return;
that.myCustomerList.forEach((element, i) => { element.IsTouchMove = false if (i == index) { if (touchMoveX > startX) { //右滑 element.IsTouchMove = false; } else { //左滑 element.IsTouchMove = true; } } }) }, angle: function(start, end) { var _X = end.X - start.X, _Y = end.Y - start.Y //返回角度 /Math.atan()返回數字的反正切值 return 360 * Math.atan(_Y / _X) / (2 * Math.PI); }
這兩個方法就是核心的左滑方法,是網上找的內容,具體哪個網站忘了;我把循環稍作修改;
angle方法是計算滑動角度的方法,防止誤操作;
原理就是滑動開始時,先循環將所有項設置為默認狀態,然后記錄當前項的坐標值;
在滑動時獲得當前坐標,計算滑動角度,大於30度直接返回;然后循環找到對應item,根據滑動后的x值和滑動開始時x值之間的關系確定是左滑還是右滑,最后修改對應屬性值;
