好了,言归正传,今天实现一个在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中的数据。
最后,感谢你们这么帅,多金,还能看到最后!!
文章中的滑动删除逻辑有参考这位兄弟: