您的当前位置:首页正文

最简单的微信小程序滑动删除

2024-11-25 来源:个人技术集锦

好了,言归正传,今天实现一个在android和ios很常见的功能,列表item滑动删除,老规矩,先上图镇楼

说完原理下面开始看实现,首先看列表xml的实现(其实小程序中没有严格意义上的列表控件,依靠for循环来生成列表)

<view class="touch-item {{item.isTouchMove ? 'touch-move-active' : ''}}" data-index="{{index}}" bindtouchstart="touchstart" bindtouchmove="touchmove" wx:for="{{items}}" wx:key="">
    <view class='content' bindtap='showDetail' data-index="{{index}}">
      <view class='column'>
        <view class='row full_width'>
          <text style='font-weight: bold;line-height:60rpx;'>{{item.name}}</text>
          <text style='margin-left:30rpx;color:gray;line-height:60rpx;'>{{item.unit}}</text>
          <text style='margin-left:20rpx;color:gray;line-height:60rpx;'>{{item.job}}</text>
        </view>
        <text style='margin-top:10rpx;color:gray;'>{{item.phone}}</text>
      </view>
    </view>
    <view class="del" catchtap="del" data-index="{{index}}">删除</view>
</view>

接着 wxss实现

.touch-item {
  display: flex;
  justify-content: space-between;
  border-bottom: 1rpx solid #ccc;
  width: 100%;
  overflow: hidden;
}
 
.content {
  width: 100%;
  padding-top: 20rpx;
  padding-bottom: 20rpx;
  padding-left: 20rpx;
  line-height: 50rpx;
  margin-right: 0;
  -webkit-transition: all 0.4s;
  transition: all 0.4s;
  -webkit-transform: translateX(180rpx);
  transform: translateX(180rpx);
  margin-left: -180rpx;
}
 
.del {
  background-color: orangered;
  width: 180rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
  -webkit-transform: translateX(180rpx);
  transform: translateX(180rpx);
  -webkit-transition: all 0.4s;
  transition: all 0.4s;
}
 
.touch-move-active .content, .touch-move-active .del {
  -webkit-transform: translateX(0);
  transform: translateX(0);
}
 
.row {
  display: flex;
  flex-direction: row;
}
 
.column {
  display: flex;
  flex-direction: column;
}
 
.full_width {
  width: 100%;
}

js中监听touch事件并处理逻辑,实现如下

//手指触摸动作开始 记录起点X坐标
  touchstart: function(e) {
    //开始触摸时 重置所有删除
    let data = App.touch._touchstart(e, this.data.items)
    this.setData({
      items: data
    })
  },
 
  //滑动事件处理
  touchmove: function(e) {
    let data = App.touch._touchmove(e, this.data.items)
    this.setData({
      items: data
    })
  },
 
  //删除事件
  del: function(e) {
    wx.showModal({
      title: '提示',
      content: '确认要删除此条信息么?',
      success: function(res) {
        if (res.confirm) {
          console.log('用户点击确定')
          that.data.items.splice(e.currentTarget.dataset.index, 1)
          that.setData({
            items: that.data.items
          })
        } else if (res.cancel) {
          console.log('用户点击取消')
        }
      }
    })
  }

对于touch事件的处理,专门封装了一个touch.js文件,如下:

var startX
var startY
class touch {
  
  constructor() {
  }
 
  _touchstart(e, items) {
    //开始触摸时 重置所有删除
    items.forEach(function (v, i) {
      if (v.isTouchMove) //只操作为true的
        v.isTouchMove = false;
    })
    
    startX = e.changedTouches[0].clientX
    startY = e.changedTouches[0].clientY
    
    return items
  }
 
  _touchmove(e, items){
      var index = e.currentTarget.dataset.index, //当前索引
      touchMoveX = e.changedTouches[0].clientX, //滑动变化坐标
      touchMoveY = e.changedTouches[0].clientY, //滑动变化坐标
      //获取滑动角度
      angle = this._angle({
        X: startX,
        Y: startY
      }, {
          X: touchMoveX,
          Y: touchMoveY
        });
    items.forEach(function (v, i) {
      v.isTouchMove = false
      //滑动超过30度角 return
      if (Math.abs(angle) > 30) return;
      if (i == index) {
        if (touchMoveX > startX) //右滑
          v.isTouchMove = false
        else //左滑
          v.isTouchMove = true
      }
    })
    return items
  }
 
  _angle(start, end) {
  var _X = end.X - start.X,
    _Y = end.Y - start.Y
  //返回角度 /Math.atan()返回数字的反正切值
  return 360 * Math.atan(_Y / _X) / (2 * Math.PI);
  }
}
 
export default touch

然后在app.json中暴露出来,重点看新加入的

//app.js
import touch from './pages/index/touch.js'//新加
App({
    ....//此处省略很多代码
  ,
  globalData: {
    userInfo: null
  },
  touch: new touch()//新加
})

由于列表数据也比较多,所以也封装到data.js中

const items = [{
  name: "祁同伟",
  sex: "男",
  group: "组织",
  phone: "13111111111",
  shortNum: "13111111111",
  mail: "13111111111@189.com",
  unit: "汉东省公安厅",
  department: "汉东省公安厅",
  job: "公安厅厅长",
  function: "管理公安厅",
  comPhone: "13111111111",
  fax: "13111111111",
  homePhone: "13111111111",
  showOrder: "",
  departOrder: "",
  remark: "汉东省公安厅厅长"
 
},
  {
    name: "欧阳菁",
    sex: "女",
    group: "群众",
    phone: "13222222222",
    shortNum: "13222222222",
    mail: "13222222222@189.com",
    unit: "京州银行",
    department: "京州银行",
    job: "京州银行行长",
    function: "管理京州银行",
    comPhone: "13222222222",
    fax: "13222222222",
    homePhone: "13222222222",
    showOrder: "",
    departOrder: "",
    remark: "京州银行行长"
  },
  {
    name: "陈岩石",
    sex: "男",
    group: "组织",
    phone: "13333333333",
    shortNum: "13333333333",
    mail: "13333333333@189.com",
    unit: "汉东省检察院",
    department: "汉东省检察院",
    job: "原察院检察长",
    function: "检察长",
    comPhone: "13333333333",
    fax: "13333333333",
    homePhone: "13333333333",
    showOrder: "",
    departOrder: "",
    remark: "原汉东省检察院检察长"
  },
  {
    name: "陆亦可",
    sex: "女",
    group: "组织",
    phone: "13555555555",
    shortNum: "13555555555",
    mail: "13555555555@189.com",
    unit: "汉东省反贪局一处",
    department: "汉东省反贪局一处",
    job: "处长",
    function: "管理一处",
    comPhone: "13555555555",
    fax: "13555555555",
    homePhone: "13555555555",
    showOrder: "",
    departOrder: "",
    remark: "汉东省反贪局一处处长"
  },
  {
    name: "林华华",
    sex: "女",
    group: "组织",
    phone: "13666666666",
    shortNum: "13666666666",
    mail: "13666666666@189.com",
    unit: "汉东省反贪局一处",
    department: "汉东省反贪局一处",
    job: "普通职员",
    function: "普通职员",
    comPhone: "13666666666",
    fax: "13666666666",
    homePhone: "13666666666",
    showOrder: "",
    departOrder: "",
    remark: "普通职员",
  },
  {
    name: "候亮平",
    sex: "男",
    group: "组织",
    phone: "13777777777",
    shortNum: "1377777777",
    mail: "13777777777@189.com",
    unit: "汉东省反贪局",
    department: "汉东省反贪局",
    job: "局长",
    function: "反贪",
    comPhone: "13777777777",
    fax: "13777777777",
    homePhone: "13777777777",
    showOrder: "",
    departOrder: "",
    remark: "汉东省反贪局局长"
  }, 
  {
    name: "孙连城",
    sex: "男",
    group: "组织",
    phone: "13555555555",
    shortNum: "13555555555",
    mail: "13555555555@189.com",
    unit: "光明区区长办公室",
    department: "光明区区长",
    job: "区长",
    function: "管理光明区",
    comPhone: "13555555555",
    fax: "13555555555",
    homePhone: "13555555555",
    showOrder: "",
    departOrder: "",
    remark: "光明区区长"
  },
  {
    name: "李达康",
    sex: "男",
    group: "组织",
    phone: "13555555555",
    shortNum: "13555555555",
    mail: "13555555555@189.com",
    unit: "京州市市委",
    department: "京州市市委",
    job: "市委书记",
    function: "管理京州市",
    comPhone: "13555555555",
    fax: "13555555555",
    homePhone: "13555555555",
    showOrder: "",
    departOrder: "",
    remark: "京州市市委书记"
  },
  {
    name: "高小琴",
    sex: "女",
    group: "群众",
    phone: "13555555555",
    shortNum: "13555555555",
    mail: "13555555555@189.com",
    unit: "山水庄园",
    department: "山水庄园",
    job: "总经理",
    function: "管理山水庄园",
    comPhone: "13555555555",
    fax: "13555555555",
    homePhone: "13555555555",
    showOrder: "",
    departOrder: "",
    remark: "管理山水庄园"
  },
]

最后在你需要引用的js文件中,如下:

var that
var items = require('../index/data.js');
const App = getApp()
Page({
  data: {
     items: []
  },
 
  onLoad: function() {
    that = this;
    /*模拟数据*/
    that.setData({
      items: items.items
    })
  },
 
//手指触摸动作开始 记录起点X坐标
  touchstart: function(e) {
    //开始触摸时 重置所有删除
    let data = App.touch._touchstart(e, this.data.items)
    this.setData({
      items: data
    })
  },
 
  //滑动事件处理
  touchmove: function(e) {
    let data = App.touch._touchmove(e, this.data.items)
    this.setData({
      items: data
    })
  },
 
  //删除事件
  del: function(e) {
    wx.showModal({
      title: '提示',
      content: '确认要删除此条信息么?',
      success: function(res) {
        if (res.confirm) {
          console.log('用户点击确定')
          that.data.items.splice(e.currentTarget.dataset.index, 1)
          that.setData({
            items: that.data.items
          })
        } else if (res.cancel) {
          console.log('用户点击取消')
        }
      }
    })
  }    
}

其实你大可以不必写我这么复杂,我写这么多,一方面为了像大家展示怎么显示稍微复杂点的布局,还一个就是告诉大家最js文件做封装来达到代码解耦的目的。如果你只是单纯的想体验下这个滑动删除,直接item展示一行文本即可,也不用data.js中的数据。

最后,感谢你们这么帅,多金,还能看到最后!!

文章中的滑动删除逻辑有参考这位兄弟:

显示全文