小程序技巧系列——侧滑组件的封装

518 阅读3分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

背景

在移动端的交互中,侧滑然后展示更多的操作功能是非常常见的,这里在微信小程序侧我们也来实现一个可以侧滑展示功能的组件,有两种方式可以实现:

  • 一种是纯CSS动画来实现
  • 一种是利用微信小程序提供的movable-view和movable-area组件来实现。

本篇文章用css的方式来实现一般,整体思路都是一样的。

实现要点

  • 防止误操作,也就是我们要计算下用户滑动的角度,是否是侧滑。这里可以用判断初始位置与最后位置的一个夹角,判断是否超过某个度数。
  • 触碰其他区域,做收起操作,由于小程序的局限性,无法获取DOM导致,如果侧滑出来的操作区域收回时,一个是用户手动收回,另一个就是触发其他区域直接收回,这里就需要将对应的事件已经索引传递到外面,供外面进行逻辑判断。
  • 一般侧滑都是用到数组相关的,比如删除操作,这时需要用户将对应的index传入进来。

实现

屏幕录制2022-02-26 下午9.43.35.gif

核心思路

  • 核心是利用transform: translateX这个CSS的动画属性,来做区域的移位。操作区隐藏的可视范围外,当用户滑动时,将其移动出来。
  • 同时只会滑出一个来,当滑动另一个时,其余的都变为收起状态。

代码实现

wxml

<view class="movable-container">
    <view class="movable-view-content {{isMove ? 'touch-move-active' : ''}}" bindtouchstart="touchStart" bind:touchmove="touchMove">
        <view class="view-content" style="transform: translateX({{optionsWidth}}rpx); margin-left: -{{optionsWidth}}rpx">
            <slot name="content"></slot>
        </view>
        <view class="view-options" style="width: {{optionsWidth}}rpx; transform: translateX({{optionsWidth}}rpx)">
            <slot name="options"></slot>
        </view>
    </view>
</view>

wxss

.movable-view-content {
    display: flex;
    width: 100%;
    overflow: hidden;
}

.view-content {
    width: 100%;
    transition: all 0.3s;
}

.view-options {
    transition: all 0.3s;
}

.touch-move-active .view-content, 
.touch-move-active .view-options {
    transform: translateX(0) !important;
}

使用该组件 在页面中引入该组件,然后对应的wxml

<block wx:for="{{slideList}}">
    <slideContainer optionsWidth="{{200}}" bind:touchStart="handleTouchStart" isTouchMove="{{item.isTouchMove}}" bind:optionShow="handleOptionShow" index="{{index}}">
      <view slot="content" class="content"></view>
      <view slot="options" class="options"></view>
    </slideContainer>
  </block>
  }
  .content {
      height: 80rpx;
      width: 100vw;
      background-color: aliceblue;
      border-bottom: 1rpx solid #ccc;
    
  }
  .options {
    height: 80rpx;
    width: 200rpx;
    background-color: red;
  }

js逻辑

Page({
  data: {
    slideList: [{value: 1}, {value:2}, {value: 3}, {value: 4}]
  },
  handleOptionShow(e) {
    const {slideList} = this.data;
    slideList.forEach((item, index) => {
      if (e.detail === index) {
        item.isTouchMove = true;
      }
    })
    this.setData({
      slideList: slideList.slice(0)
    })
  },
  handleTouchStart(e) {
    const {slideList} = this.data;
    // 防止用户多触点触发,也就是多手指
    if(e.detail.touches.length > 1) {
      return;
    }
    slideList.forEach((item, index) => {
      if (e.detail.index !== index) {
        item.isTouchMove = false;
      }
    })
    this.setData({
      slideList: slideList.slice(0)
    })
  },
})

注意点: 这里我们是在使用的组件,对滑块做处理,在用户触碰滑块以及操作区展示出来时,分别发送对应的事件,将当前的index传入。 每一项都记录一个状态,是否处于展示操作区,用来处理当用户滑动其他项时,将其收起。

总结

其实实现一个侧滑组件还是很简单的,但难点是如何保证我们的体验,这里总结了3点:

  • 一个是误操作问题,注意用户滑动方向,防止将用户非滑动操作,引起滑块的滑动
  • 而是防止用户的多手势操作,这里只判断一个触点的情况,对于多触点不进行任何触发
  • 同时只存在一项滑动中的状态,其他项都是收起状态。