一 需求
在列表中,希望某一项左滑或长按能支持删除。
二 准备
1 WXML
<view class="shop-list">
<view class="check-all-box">
<view>
<label class="check-around8" bindtap="onCheckAll" data-lor='1'>
<radio checked="{{allSelected?true:false}}" color="#000"></radio>
<text class="check-all">{{checkAllText}}全选</text>
</label>
</view>
</view>
<view class="item-box {{item.isTouchMove ? 'touch-move-active' : ''}}"
bindtouchstart="touchstart"
bindtouchend="touchend"
bindtouchmove="touchmove"
bindlongpress="longtap"
bindtap="getInfo"
data-item="{{item}}"
data-index="{{index}}"
wx:for="{{list}}"
wx:key="index">
<view class="item-test">
<view class="item-check-test" catchtap="selecedItem" data-id="{{item.id}}">
<radio checked="{{item.isSelect>0?true:false}}" color="#000"></radio>
</view>
<view class="item-img-test">
<image class="item-img" src="{{item.thumbUrl}}" />
</view>
<view class="item-info-test">
<view class="item-title">{{item.title}}</view>
<view class="item-spec">{{item.spec}}</view>
<view class="item-bottom">
<view class="item-price">¥{{item.price}}</view>
<view class="num-box">
<view class="num-desc" data-id="{{item.id}}" data-total="{{item.total}}" bindtap="reduce">-</view>
<input class="item-input" type="number"disabled="boolean" value="{{item.total}}" />
<view class="num-plus" data-id="{{item.id}}" data-total="{{item.total}}" bindtap="plus">+</view>
</view>
</view>
</view>
</view>
<view class="remove" data-id="{{item.id}}" bindtap="remove">{{remove}}删除</view>
</view>
</view>
2 SCSS
page {
background-color: #f8f8f8;
}
.shop-list {
display: flex;
flex-direction: column;
margin-top: 30rpx;
padding-bottom:120rpx;
.check-all-box {
display: flex;
align-items: center;
padding: 30rpx;
background-color: #fff;
.check-all {
margin-left: 20rpx;
font-size: 30rpx;
}
}
.item-box {
margin-bottom: 20rpx;
position: relative;
z-index: 99;
font-size: 14px;
display: flex;
justify-content: space-between;
border-bottom:1px solid #ccc;
width: 100%;
overflow: hidden;
.item-test {
display: flex;
align-items: center;
padding: 30rpx;
background-color: #fff;
position: relative;
z-index: 99;
width: 100%;
margin-right:0;
-webkit-transition: all 0.4s;
transition: all 0.4s;
-webkit-transform: translateX(90px);
transform: translateX(90px);
margin-left: -90px;
.item-check-test {
flex: 1;
}
.item-img-test {
flex: 3;
margin-left: 5rpx;
margin-right: 20rpx;
.item-img {
width: 180rpx;
height: 180rpx;
border-radius: 5rpx;
border: 1rpx solid #eaeaea;
}
}
.item-info-test {
flex: 14;
display: flex;
flex-direction: column;
.item-spec {
margin-top: 10rpx;
}
.item-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 10rpx;
.num-box {
display: flex;
align-items: center;
justify-content: flex-end;
font-size: 30rpx;
.num-desc {
padding: 0 10rpx;
color: #999;
border: 4rpx solid #999;
}
.item-input {
width: 80rpx;
text-align: center;
}
.num-plus {
padding: 0 10rpx;
color: #fff;
background-color: #000;
border: 4rpx solid #000;
}
}
}
}
}
.remove {
background-color: orangered;
width: 90px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
-webkit-transform: translateX(90px);
transform: translateX(90px);
-webkit-transition: all 0.4s;
transition: all 0.4s;
}
}
.touch-move-active {
.item-test {
-webkit-transform: translateX(0);
transform: translateX(0);
}.item {
-webkit-transform: translateX(0);
transform: translateX(0);
}
.remove {
-webkit-transform: translateX(0);
transform: translateX(0);
}
}
}
3 Typescript
data = {
pageId: '',
title: '',
allSelected: false,
list: [
{
id: '0',
thumbUrl: 'https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1599639633&di=d8d3447ad9c7ec3947746481dc8551d4&src=http://cp2.douguo.net/upload/caiku/b/b/1/600x400_bbe82c7b8a99820c8be64019c5e9d291.jpg',
title: '水果大拼盘水果大拼盘水果大拼盘水果大拼盘',
spec: '特别好吃的水果大拼盘',
price: '99.10',
num: 1,
total: 12,
isSelect: false
},
{
id: '1',
thumbUrl: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599649715761&di=a48f8ea1bcd93af81788c36de8ec45b0&imgtype=0&src=http%3A%2F%2Fwww.gzsthb.com%2Fzb_users%2Fupload%2F2020%2F01%2F20200108122126_96004.jpg',
title: '大橘子大橘子大橘子大橘子',
spec: '大橘子不酸',
price: '1.10',
num: 1,
total: 2,
isSelect: false
},{
id: '2',
thumbUrl: 'https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1599639633&di=d8d3447ad9c7ec3947746481dc8551d4&src=http://cp2.douguo.net/upload/caiku/b/b/1/600x400_bbe82c7b8a99820c8be64019c5e9d291.jpg',
title: '水果大拼盘',
spec: '水果大拼盘',
price: '99.20',
num: 1,
total: 13,
isSelect: false
},{
id: '3',
thumbUrl: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599649715761&di=523a9a75a49e3b78a73af6dae347f951&imgtype=0&src=http%3A%2F%2Fpic.haixia51.com%2Fpic%2F%3Fp%3D%2Fhuahuibk%2F20190213%2F14%2F1550040370-ebHEFGfltD.jpg',
title: '葡萄葡萄葡萄葡萄葡萄葡萄',
spec: '葡萄',
price: '9.20',
num: 1,
total: 12,
isSelect: false
}
],
startX: 0, //开始坐标
startY: 0,
touch_start: 0, // 开始时间
touch_end: 0
}
}
/**
* @desc 手指触摸动作开始 记录起点X坐标
* @param e 当前项
*/
touchstart(e) {
let me = this;
let list = me.data.list;
let startX = e.changedTouches[0].clientX;
let startY = e.changedTouches[0].clientY;
let touch_start = e.timeStamp;
// 开始触摸时 重置所有删除
list.forEach(function (v, i) {
if (v.isTouchMove)//只操作为true的
v.isTouchMove = false;
})
me.setData({
startX: startX,
startY: startY,
list: list,
touch_start: touch_start
})
}
/**
* @desc 离开时,获得时间
* @param e 当前项
*/
touchend(e) {
let me = this;
let touchEnd = e.timeStamp;
me.setData({
touch_end: touchEnd
})
}
/**
* @desc 长按触发
* @param e 当前项
*/
longtap(e) {
let that = this;
let start = that.data.touch_start;
let end = that.data.touch_end;
if (start - end >= 5000) {
that.remove(e);
}
}
/**
* @desc 滑动事件
* @param e 当前项
*/
touchmove(e) {
var that = this,
index = e.currentTarget.dataset.index,//当前索引
startX = that.data.startX,//开始X坐标
startY = that.data.startY,//开始Y坐标
touchMoveX = e.changedTouches[0].clientX,//滑动变化坐标
touchMoveY = e.changedTouches[0].clientY,//滑动变化坐标
//获取滑动角度
angle = that.angle({ X: startX, Y: startY }, { X: touchMoveX, Y: touchMoveY });
that.data.list.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
}
})
//更新数据
that.setData({
list: that.data.list
})
}
/**
* 计算滑动角度
* @param {Object} start 起点坐标
* @param {Object} end 终点坐标
*/
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);
}
/**
* @desc 删除功能
* @param e 当前项
*/
remove(e) {
let that =this;
let list = that.data.list;
let id = e.currentTarget.dataset.id;
var index = list.findIndex(function(item) {
return item.id == id;
});
wx.showModal({
title: '温馨提示!',
content: '你确认删除吗?',
success: function (res) {
if (res.confirm) {
if (index != -1) {
list.splice(index, 1)
}
that.setData({
list:list
})
} else{
console.log('用户点击取消')
}
}
})
}
/**
* @desc 全选功能
*/
onCheckAll() {
let me = this;
let allSelected = !me.data.allSelected;
let list = me.data.list;
for(let i = list.length; i--;) {
list[i].isSelect = allSelected;
}
me.setData({
allSelected: allSelected,
list: list
})
}
/**
* @desc 获得详情
* @param e 当前项
*/
getInfo(e) {
let item = e.currentTarget.dataset.item;
console.log(item);
}
/**
* @desc 列表中某一项的选中
* @param e 当前项
*/
selecedItem(e) {
let me = this;
let id = e.currentTarget.dataset.id;
let allSelected = true;
let list = me.data.list;
list.map((item, k) => {
if (item.id == id) {
item.isSelect = !item.isSelect;
}
})
for(let i = list.length; i--;) {
if (!list[i].isSelect) {
allSelected = false;
}
}
me.setData({
allSelected: allSelected,
list: list
})
}
三 效果图
1 开发者工具效果图
- 支持左滑删除
点击删除,触发弹框
- 支持长按删除