微信小程序(二)学妹问我微信小程序左滑删除怎么实现

4,184 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

背景

上篇文章记录了小程序的自定义导航栏的实现过程和小程序基础组件 cover-image 中 使用 fiexd 失效的坑。
前天突然在qq上看到一个学妹在群里@我问我小程序怎么实现左滑删除,今天正好周末有空,于是就在掘金上写了这篇文章。

效果展示

aaa.gif

实现过程

  • 用小程序基础组件 movable-areamovable-view 搭建视图架子
  • 拿到后台的商品数据循环展示
  • 左滑展示右侧隐藏的红色删除按钮
  • 点击按钮,通过 dataset 拿到当前索引,删除数组中对应的数据

伪代码:

<block wx:for="{{infoList}}" wx:for-index="index" wx:key="id" wx:for-item="item">
  <movable-area >
    <movable-view class="item" damping="100" direction="horizontal" out-of-bounds="true" animation="true">
      <!-- 滑动删除左边显示信息的盒子 -->
      <view></view>
      <!-- 右边删除按钮的盒子 -->
      <view bindtap="handleDelShop">删除</view>
    </movable-view>
  </movable-area>
</block>
    
  // js 代码  
  // 删除商品处理事件
async handleDelShop(e) {
    let { index, id } = e.currentTarget.dataset;
    let infoList = this.data.cartData.goods;
    infoList.splice(index, 1);
    this.setData({
      [infoList]: infoList,
    })
},

需要注意的地方

  • 左边显示的区域宽度一定要设置 100vw,并且加上 overflow: hidden 防止出现x轴方向的滑动条,在外层的整个盒子加上 box-sizing: border-box;

  • 给基础组件设置高度 movable-areamovable-view 是有默认的高度的,必须设置这两个基础组件的高度,如果不设置的话,就算里面的盒子有固定高度,也不会生效的,所以特别一定要注意,设置固定高度,在写代码前就要算好里面的盒子的高度,如果因为数据不确定,根据不同数据展示不同高度的话,可以用条件判断,设置不同高度。

优化

为了用户体验更好,我做了一下优化,类似这种效果:

20200331112850281.gif

(因为在网吧写的文章,没有动图素材,就用了别人的动态图,忘记来源了,不过放心哈,代码实现的效果是一样的!有知道动态来源的可以告诉我,后面我加上。)

做了以下优化:

  • 判断上下滑动还是左右滑动,上下滑动则复原所有项的样子(隐藏所有项的删除按钮)。
  • 左滑另一个项时,其他项的删除按钮全隐藏,只显示一个项的删除。
  • 左滑距离超过 20px 就自动滑到能显示完整的删除按钮的样子。小于 20px 则恢复原来的样子(隐藏删除按钮)

ok,废话不多说了看具体代码:

<block wx:for="{{infoList}}" wx:for-index="index" wx:key="id" wx:for-item="item">
  <movable-area >
    <movable-view bindtouchstart="touchStart" data-index="{{index}}" bindtouchend="touchend" class="item" x="{{shopInfo.x}}" y="{{shopInfo.y}}" damping="100" direction="horizontal" out-of-bounds="true" animation="true">
      <!-- 滑动删除左边显示信息的盒子 -->
      <view></view>
      <!-- 右边删除按钮的盒子 -->
      <view bindtap="handleDelShop">删除</view>
    </movable-view>
  </movable-area>
</block>
    
  // js 代码 data 里的变量:
data: {
    currentTouche: {
      x: 0,
      y: 0
    },
    offset: 20,
},
  
  // 删除商品处理事件
async handleDelShop(e) {
    let { index, id } = e.currentTarget.dataset;
    let infoList = this.data.cartData.goods;
    infoList.splice(index, 1);
    this.setData({
      [infoList]: infoList,
    })
},
  touchStart(e) {
    let { clientX, clientY } = e.changedTouches[0];
    let { index } = e.currentTarget.dataset;

    // 重置列表除当前操作的项之外的所有项在x方向的偏移量
    let newCartData = this.data.infoList.map((v, idx) => {
      if (index != idx) {
        v.x = '';
        v.y = '';
      }
      return v;
    })
    this.setData({
      infoList: newCartData
    })

    this.setData({
      currentTouche: {
        x: clientX,
        y: clientY
      }
    })
  },
  touchend(e) {
    let { clientX, clientY } = e.changedTouches[0];
    let { index } = e.currentTarget.dataset;
    // 判断是上下滑还是左右滑
    if (Math.abs(clientY - this.data.currentTouche.y) < Math.abs(clientX - this.data.currentTouche.x)) {  // 左右滑动
      // 判断是左滑还是右滑
      if (clientX >= this.data.currentTouche.x) {  // 右滑
        this.setData({
          [`infoList[${index}].x`]: 0
        })
      } else {   //左滑
        if (this.data.currentTouche.x - clientX >= this.data.offset) {
          this.setData({
            [`infoList[${index}].x`]: -rpxTopx(164)
          })
        } else {
          this.setData({
            [`infoList[${index}].x`]: 0
          })
        }
      }
    } else {  // 上下滑动
      // 重置数据
      this.setData({
        [`infoList[${index}].x`]: 0
      })
    }
    this.setData({
      currentTouche: {
        x: clientX,
        y: clientY
      }
    })
  },

代码解释:通过 touchStart 和 touchEnd 事件可以知道滑动开始时的位置和滑动结束后的位置。

image.png 获取 changedTouches[0] 触摸点的位置信息 image.png changedTouches 里一项的属性 image.png

  1. 先判断上下滑动的距离是否大于左右滑动的距离,如果大于则为上下滑动并且重置位置数据,否则为左右滑动,
  2. 如果为左右滑动时判断左滑还是右滑,左滑时:左滑距离超过 20px 就自动滑到能显示完整的删除按钮的样子。小于 20px 则恢复原来的样子(隐藏删除按钮)。如果右滑时重置 x 轴方向的位置数据(让删除按钮隐藏,恢复到原来的样子)。

总结

功能实现起来很简单,但是刚开始因为时间比较紧迫,就做的比较匆忙,后就有需要优化用户体验的地方,比如左滑移动的距离在 20px 以内松手后应该反弹回原来的位置,超过 20px 松手后应该自动滑动到百分之100。

因为小程序对用户来说比较方便,所以一般的toC的项目都会有小程序端。总之希望这边文章对小伙伴们有作用!感觉还不错的话可以点赞收藏起来,以备不时之需(说不定下次公司就让你写这种小程序类似的需求了呢😂)

写在最后

我是 AndyHu,目前暂时是一枚前端搬砖工程师。

文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注呀😊

未经许可禁止转载💌

speak less,do more.