剛接觸微信小程序不久,在做的項目是個微商城. 其中購物車中需要用到滑動刪除功能. 原本在其他平台上利用JS操作DOM計算坐標即可完成,但是小程序的bindtouchmouve,bindtouchend和bindtouchstart事件會冒泡到父級控件,在真機測試中會導致整屏都觸發自定義的滑動事件,真個界面都成了萬花筒. 如果使用catchtouchmove,catouchend和catchstart. 是可以防止冒泡. 左右也可以正常滑動.但是不僅僅是小程序的橫向scroll事件,小程序的縱向scroll事件也會無法觸發. 也就是會導致當前頁面無法上下滑動.
我試過用scroll-view控件, 在小程序官方文檔中說明scroll-x="false"能禁止x軸滾動. 實際上不管在真機還是微信開發者中都無法起作用. 后來經過多方實驗,發現只要滑動模塊超過當前屏幕可視寬度,bindtouchmove就會冒泡進而觸發整屏滑動,即使刪除按鈕只是用絕對定位固定在右側也不行, 例如下圖windowWidth為414px, 產品Item寬也是414px,但是加上刪除按鈕就超出了414px. 滑動時就會觸發整屏滑動.
實在沒有辦法,后來想到Css3里面的transform變換也可以實現移動的效果,而且移動的距離是不是不計入模塊的寬度呢?首先先用刪除按鈕做測試:
把刪除按鈕用絕對定位定在Item內右側,然后利用transform平移到item外右側. 用真機測試,果然左右滑動不會再觸發整個View的滑動了.
1 .item .btn-del{ 2 position: absolute; 3 display: flex; 4 top:0px; 5 right:0px; 6 color: #fff; 7 background: #fd4346; 8 height: 100%; 9 border-radius: 0px; 10 border: none; 11 align-items: center; 12 transform:translate(64px,0); 13 -ms-transform:translate(64px,0); 14 -moz-transform:translate(64px,0); 15 -webkit-transform:translate(64px,0); 16 -o-transform:translate(64px,0); 17 }
接下來很簡單只要把item也利用transform跟隨用戶手勢左右平移即可. 計算用戶平移距離和平常一樣,我寫的比較粗糙,隨便一看,
WXML:
<view class="item" data-matindex="{{matIndex}}" bindtouchend="touchEndToDel" bindtouchstart="touchStartToDel" bindtouchmove="touchMoveToDel" style="webkit-transform:translate({{matItem.moveLeft}}px,0);-webkit-transform:translate({{matItem.moveLeft}}px,0);" wx:for="{{matList}}" wx:for-item="matItem" wx:for-index="matIndex" wx:key="skuguid">
<view class="shop-image" > <icon wx:if="{{matItem.selected}}" type="success" size="20" color="#2da4e6" class="my-check"/> <icon wx:else type="circle" size="20" class="my-check"/> <image src="{{matItem.imageaddress}}" style="width:180rpx;height:180rpx;"></image> </view> <view class="shop-title" bindtap="tapBackDelBtn"data-matindex="{{matIndex}}"> <text>{{matItem.matname}}</text> <view class="h2 num" wx:if="{{mat.isEdit}}"> <view class="flex flex-wrap" > <view bindtap="minusNum" data-matindex="{{matIndex}}" class="flex-item">-</view> <view class="flex-item"> <input type="text" value="{{matItem.digit}}"/> </view> <view bindtap="plusNum" data-matindex="{{matIndex}}" class="flex-item">+</view> </view> </view> <view class="price">{{matItem.showprice}}</view> </view> <view class="shop-price" > <view></view> <view>x{{matItem.digit}}</view> </view> <!-- 彈出按鈕-刪除 --> <button bindtap="removeSingle" wx:if="{{!mat.isEdit }}" data-matindex="{{matIndex}}" class="btn-del" >刪除</button> </view> </view>
var moveXList = [0, 0]//X軸移動的距離
/** * 輕觸回收指定刪除按鈕 */ tapBackDelBtn:function(e){var matIndex = e.currentTarget.dataset.matindex that.backDelBtn(matIndex) }, /** * 收回彈出刪除按鈕 * matIndex:skuBody下標 * 如果不傳表示全部收回 */ backDelBtn:function(matIndex){ if (!vpUtilService.vpIsNull(matIndex)){ that.data.matList.forEach(function(item,index){ item.moveLeft = 0 }) } else {
that.data.matList[matIndex].moveLeft = 0 } that.setData({ matList: that.data.matList}) }, /** * bindtouchmove */ touchMoveToDel:function(e){ if (e.touches.length != 1 ){return} if (moveXList[1] == 0){ moveXList.shift() moveXList.push(e.touches[0].clientX) return }var matIndex = e.currentTarget.dataset.matindex var moveLeft = that.data.matList[matIndex].moveLeft if ((moveLeft<=0) || (moveLeft>-64)){//移動范圍在 -64px~0之間 var dis = moveXList[1] - moveXList[0] moveLeft = parseInt(moveLeft?moveLeft:0) + parseInt(dis) moveLeft = moveLeft < -64? -64: moveLeft moveLeft = moveLeft > 0 ? 0 : moveLeft moveXList.shift() moveXList.push(e.touches[0].clientX) that.data.matList[matIndex].moveLeft = moveLeft that.setData({ matList: that.data.matList}) } }, /** * bindtouchend */ touchEndToDel: function (e) { var matIndex = e.currentTarget.dataset.matindex var moveLeft = that.data.matList[matIndex].moveLeft if(moveLeft<-32){//移動超過一半的距離,彈出刪除按鈕 that.data.matList[matIndex].moveLeft = -64 }else{//小於一半的距離,收回 that.data.matList[matIndex].moveLeft = 0 } that.setData({ matList: that.data.matList}) }, /** * bindtouchstart */ touchStartToDel: function (e) { moveXList = [0,0] },