做移动端开发,手机屏幕都是寸土寸金,界面要美观简洁,又要功能强大,所以说程序猿都是很苦逼的。
所谓一猿有难,八个项目经理围观,此处省略一万字。。。
好了,言归正传,今天实现一个在android和ios很常见的功能,列表item滑动删除,老规矩,先上图镇楼
欧阳菁被我翻牌子了,看这就是贪污的下场,#@&@#。。。,哎呀又扯远了
实现原理就是:
1、将你要展示的布局和删除按钮放在同一个父item布局中,水平排列
2、让你要展示的布局充满屏幕,通过css样式让超出的删除按钮隐藏
3、监听touch事件,平移布局显示和隐藏删除按钮
说完原理下面开始看实现,首先看列表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 startXvar startYclass 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.jsimport 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 thatvar 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('用户点击取消') } } }) } }好了,到这里基本大功告成了。(友情提示,我这里的touch.js和data.js都和引用它们的index.js放在同一目录下面)
其实你大可以不必写我这么复杂,我写这么多,一方面为了像大家展示怎么显示稍微复杂点的布局,还一个就是告诉大家最js文件做封装来达到代码解耦的目的。如果你只是单纯的想体验下这个滑动删除,直接item展示一行文本即可,也不用data.js中的数据。
最后,感谢你们这么帅,多金,还能看到最后!!
文章中的滑动删除逻辑有参考这位兄弟:https://blog.csdn.net/mi_ni123/article/details/80021048
小程序













