小程序实现滑动删除

随着UI的不断优化,对功能的要求也越来越高。以前可能是直接提供一个删除按钮给用户,但在页面布局上可能看上去有些多余,这篇文章带大家在小程序实现左滑删除效果。

在这里插入图片描述

一、使用movable-view实现

在这里插入图片描述
简单解读一下movable-area标签的基本概念。movable-area标签就是定义了一个可移动的视图容器,支持在页面中拖拽滑动,跟普通的view容器是一样的,但是也有不同之处,movable-area必须设置width和height属性,不设置默认为10px;movable-view 默认为绝对定位,top和left属性为0px。

 	  <movable-area>
        <movable-view out-of-bounds="true" direction="horizontal" inertia="true">
        </movable-view>
      </movable-area>

我们需要用的一些属性out-of-bounds,给他定义true,让我们的容器超过可移动区域后,movable-view还可以移动,direction属性是定义我们滑动的方向,vertical是垂直滑动,horizontal是水平滑动。

二、使用Touch事件实现滑动

1.bindtouchstart 函数,手指触摸动作开始
2.bindtouchmove 函数,手指触摸后移动
3.bindtouchend 函数,手指触摸动作结束

实现思路:
1.页面上的容器分为上下两层,上面一层显示正常加载无动作的内容,下面一层显示容器触发事件后展示的内容,例如删除、置顶、标为未读等按钮。
2.每个容器上面那一层容器我们通过css使用定位来固定,通过操纵事件来实现向需要移动的方向移动。
3.通过官方文档提供的API来实现容器随着方向移动。

三、完整代码

1.wxml

<view class="">
  <view class="containerTitle">使用movable-view实现左滑</view>
  <view class="list">
    <view class="product-item" wx:for="{{productList}}" wx:for-index="index" wx:key="{{item.id}}" >
      <movable-area>
        <movable-view out-of-bounds="true" direction="horizontal" x="{{item.xmove}}"
          inertia="true"
          data-productIndex="{{index}}"
          bindtouchstart="handleTouchStart"
          bindtouchend="handleTouchEnd"
          bindchange="handleMovableChange">
          <view class="product-item-wrap">
            <view class="product-movable-item">
              <view class="product-movable-item-name">{{item.name}}</view>
              <view class="product-movable-item-code">{{item.code}}</view>
            </view>
            <view class="product-movable-item product-movable-item-amount">
              <text class="amount">{{item.amount}}</text>
              <text class="unit"></text>
            </view>
          </view>
        </movable-view>
      </movable-area>
      <view class="delete-btn" data-id="{{item.id}}" bindtap="handleDeleteProduct">删除</view>
    </view>
  </view>
  <view class="containerTitle">使用Touch事件实现左滑</view>
  <view class="list">
    <view class="product-item" wx:for="{{slideProductList}}" wx:for-index="index" wx:key="{{item.id}}">
      <slide-delete pid="{{item.id}}" bindaction="handleSlideDelete" wx:key="{{item.id}}">
        <view class="product-item-wrap">
          <view class="product-movable-item">
            <view class="product-movable-item-name">{{item.name}}</view>
            <view class="product-movable-item-code">{{item.code}}</view>
          </view>
          <view class="product-movable-item product-movable-item-amount">
            <text class="amount">{{item.amount}}</text>
            <text class="unit"></text>
          </view>
        </view>
      </slide-delete>
    </view>
  </view>
</view>

2.wxss

.containerTitle {
  margin: 60rpx 0 30rpx;
  font-size: 40rpx;
  text-align: center;
  font-weight: bold;
  color: #383A3D;
}

.list .product-item {
  position: relative;
  width: 100vw;
  border-bottom: 2rpx solid #E9E9E9;
  box-sizing: border-box;
  background: #fff;
  z-index: 999;
}

.slide-product-list .slide-product-item {
  position: relative;
  width: 100vw;
  border-bottom: 2rpx solid #E9E9E9;
  box-sizing: border-box;
  background: #fff;
  z-index: 999;
}

.list .product-item movable-area {
  height: 120rpx;
  width: calc(100vw - 120rpx);
}

.list .product-item movable-view {
  height: 120rpx;
  width: 100vw;
  background: #fff;
  z-index: 999;
}

.list .product-item .delete-btn {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0; 
  width: 120rpx;
  font-family: PingFangSC-Regular;
  font-size: 24rpx;
  color: #FFFFFF;
  line-height: 120rpx;
  z-index: 1;
  background: red;
  text-align: center;
}

.list .product-item-wrap {
  position: relative;
  display: flex;
  align-items: center;
  padding: 8rpx 0 20rpx 20rpx;
  box-sizing: border-box;
}

.list .product-item-wrap .product-movable-item {
  flex: 1;
  overflow: hidden;
}

.list .product-item-wrap .product-movable-item-name {
  font-family: PingFangSC-Regular;
  font-size: 28rpx;
  color: #71747A;
  line-height: 60rpx;
  margin-right: 10rpx;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.list .product-item-wrap .product-movable-item-code {
  font-family: PingFangSC-Regular;
  font-size: 24rpx;
  color: #969AA3;
}

.list .product-item-wrap .product-movable-item-amount {
  flex: 0 0 auto;
  padding-right: 80rpx;
  position: relative;
}

.list .product-item-wrap .product-movable-item-amount .amount {
  width: 120rpx;
  font-size: 28rpx;
  color: #383A3D;
  line-height: 60rpx;
}

.list .product-item-wrap .product-movable-item-amount .unit {
  position: absolute;
  top: 0;
  right: 30rpx;
  font-size: 28rpx;
  color: #969AA3;
  line-height: 60rpx;
}

3.js代码

//获取应用实例
const app = getApp()

Page({
  data: {
    productList: [
      {
        id: 1,
        name: '31省市区新增境外输入13例',
        code: 'Jin日头条',
        amount: 5
      },
      {
        id: 2,
        name: '饲养员遭熊攻击身亡',
        code: 'bai度新闻',
        amount: 4
      },
      {
        id: 3,
        name: '安倍晋三参拜靖国神社',
        code: '日媒',
        amount: 10
      }
    ],
    slideProductList: [
      {
        id: 4,
        name: '老兵回忆参加抗美援朝说今生无悔',
        code: 'xin微博',
        amount: 101
      },
      {
        id: 5,
        name: '女子下楼时玩手机踩空摔伤',
        code: 'zz资讯',
        amount: 500
      },
      {
        id: 6,
        name: '杨紫为离线庆生',
        code: 'xx新闻',
        amount: 110
      }
    ]
  },

  onLoad: function () {

  },

  /**
   * 显示删除按钮
   */
  showDeleteButton: function (e) {
    let productIndex = e.currentTarget.dataset.productindex
    this.setXmove(productIndex, -65)
  },

  /**
   * 隐藏删除按钮
   */
  hideDeleteButton: function (e) {
    let productIndex = e.currentTarget.dataset.productindex

    this.setXmove(productIndex, 0)
  },

  /**
   * 设置movable-view位移
   */
  setXmove: function (productIndex, xmove) {
    let productList = this.data.productList
    productList[productIndex].xmove = xmove

    this.setData({
      productList: productList
    })
  },

  /**
   * 处理movable-view移动事件
   */
  handleMovableChange: function (e) {
    if (e.detail.source === 'friction') {
      if (e.detail.x < -30) {
        this.showDeleteButton(e)
      } else {
        this.hideDeleteButton(e)
      }
    } else if (e.detail.source === 'out-of-bounds' && e.detail.x === 0) {
      this.hideDeleteButton(e)
    }
  },

  /**
   * 处理touchstart事件
   */
  handleTouchStart(e) {
    this.startX = e.touches[0].pageX
  },

  /**
   * 处理touchend事件
   */
  handleTouchEnd(e) {
    if(e.changedTouches[0].pageX < this.startX && e.changedTouches[0].pageX - this.startX <= -30) {
      this.showDeleteButton(e)
    } else if(e.changedTouches[0].pageX > this.startX && e.changedTouches[0].pageX - this.startX < 30) {
      this.showDeleteButton(e)
    } else {
      this.hideDeleteButton(e)
    }
  },

  /**
   * 删除产品
   */
  handleDeleteProduct: function ({ currentTarget: { dataset: { id } } }) {
    let productList = this.data.productList
    let productIndex = productList.findIndex(item => item.id === id)
    productList.splice(productIndex, 1)
    this.setData({
      productList
    })
    if (productList[productIndex]) {
      this.setXmove(productIndex, 0)
    }
  },

  /**
   * slide-delete 删除产品
   */
  handleSlideDelete({ detail: { id } }) {
    let slideProductList = this.data.slideProductList
    let productIndex = slideProductList.findIndex(item => item.id === id)
    slideProductList.splice(productIndex, 1)
    this.setData({
      slideProductList
    })
  }
})

评论 7 您还未登录,请先 登录 后发表或查看评论
相关推荐

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

kitten-iio

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值