头图

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

背景

上篇文章记录了小程序的自定义导航栏的实现过程和小程序基础组件 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.

17 声望
0 粉丝
0 条评论
推荐阅读
微信小程序(四)绝对不可错过切换自定义菜单栏的骚操作
在开发小程序的时候,一般的小程序用官方自带的菜单栏就够了,但一但稍微复杂的小程序可能因为产品经理的一句“页面太多了得加个菜单”,就可能要对菜单栏进行增、删、改的操作,这个时候自带的就满足不了需求了,...

AndyHu阅读 722

封面图
ESlint + Stylelint + VSCode自动格式化代码(2023)
安装插件 ESLint,然后 File -&gt; Preference-&gt; Settings(如果装了中文插件包应该是 文件 -&gt; 选项 -&gt; 设置),搜索 eslint,点击 Edit in setting.json

谭光志34阅读 20.8k评论 9

安全地在前后端之间传输数据 - 「3」真的安全吗?
在「2」注册和登录示例中,我们通过非对称加密算法实现了浏览器和 Web 服务器之间的安全传输。看起来一切都很美好,但是危险就在哪里,有些人发现了,有些人嗅到了,更多人却浑然不知。就像是给门上了把好锁,还...

边城32阅读 7.3k评论 5

封面图
vue UI框架比较
最好基于vue2.0PC端:因为用过的是饿了么UI,所以比较以饿了么UI为基础element UI 饿了么UI支持vue2.x80分优点:组件的API方法、属性等封装的较为完善缺点:样式有些生硬,不够炫酷美观N3 N3支持vue2.x70分优点:...

chinawzc22阅读 39.9k评论 17

涨姿势了,有意思的气泡 Loading 效果
今日,群友提问,如何实现这么一个 Loading 效果:这个确实有点意思,但是这是 CSS 能够完成的?没错,这个效果中的核心气泡效果,其实借助 CSS 中的滤镜,能够比较轻松的实现,就是所需的元素可能多点。参考我们...

chokcoco24阅读 2.2k评论 3

在前端使用 JS 进行分类汇总
最近遇到一些同学在问 JS 中进行数据统计的问题。虽然数据统计一般会在数据库中进行,但是后端遇到需要使用程序来进行统计的情况也非常多。.NET 就为了对内存数据和数据库数据进行统一地数据处理,发明了 LINQ (L...

边城17阅读 2k

封面图
过滤/筛选树节点
又是树,是我跟树杠上了吗?—— 不,是树的问题太多了!🔗 相关文章推荐:使用递归遍历并转换树形数据(以 TypeScript 为例)从列表生成树 (JavaScript/TypeScript) 过滤和筛选是一个意思,都是 filter。对于列表来...

边城18阅读 7.8k评论 3

封面图
17 声望
0 粉丝
宣传栏