给列表添加左滑出现删除按钮的效果,经常出现在类似购物车的实例中。今天我们一起实现下这个效果。基于uniapp,h5端同理
<template>
<view class="list-item">
<!-- 滑动容器 -->
<view
class="swipe-container"
@touchstart="onTouchStart"
@touchmove="onTouchMove"
@touchend="onTouchEnd"
:style="{transform:‘translateX(’+moveX+'px)}"
>
<!-- 列表项内容 -->
<view class="content">
<!-- 列表项内容 -->
<!-- ... -->
测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容测试内容
</view>
<!-- 删除选项 -->
<!-- <view v-if="showDeleteOption" class="delete-option" :style="deleteOptionStyle" @click="deleteItem">
删除
</view> -->
<view class="delete-option" @click="deleteItem">
删除
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
startX: 0, // 记录触摸起始位置
moveX: 0, // 记录横向位移
showDeleteOption: false,
isAnimating: false,
delBtnWidth:100,
distance:0
};
},
methods: {
onTouchStart(event) {
// 记录触摸起始位置
this.startX = event.touches[0].clientX;
},
onTouchMove(event) {
// 计算横向位移
this.moveX = event.touches[0].clientX - this.startX;
console.log("movex",this.moveX)
if(this.moveX>=0){
this.moveX=0
}else{
if(this.moveX<-this.delBtnWidth/2){
this.moveX=-this.delBtnWidth
}
}
},
onTouchEnd() {
if(this.moveX<0){
if(Math.abs(this.moveX)<this.delBtnWidth/2){
this.moveX=0
}else{
this.moveX=-this.delBtnWidth
}
}
},
}
}
</script>
<style>
.swipe-container {
position: relative;
height: 100%;
/* overflow: hidden;
*/ touch-action: pan-y; /* 允许垂直方向滚动 */
transition: all 0.5s;
}
.delete-option {
position: absolute;
top: 0;
right: -100px;
height: 100%;
width: 100px;
background-color: red;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
transition: opacity 0.3s;
}
.content {
height: 100%;
padding-right: 100px; /* 设置内容右侧距离为删除选项的宽度 */
}
</style>
这里我们只是对单个的选项做了左滑删除操作,那对于列表而言,我们则需要对数据进行一点改造:
<view class="message_list">
<view class="item" v-for="(item, index) in list" :key="index">
<view class="time_name">时间段({{index+1}})</view>
<view class="time_item"
@touchstart="drawStart($event,item)"
@touchmove="drawMove($event,item)"
@touchend="drawEnd($event,item)"
:style="{transform:'translateX('+item.moveX+'px)'}"
>
<view class="item_cont">
<view class="start_item" >
<view class="start_item_title">开始时间</view>
<view @click="triggerTime(item)">{{item.startTime||"--"}}</view>
</view>
<view class="end_item" >
<view class="end_item_title">结束时间</view>
<view @click="triggerTime(item)">{{item.endTime||"--"}}</view>
</view>
</view>
<view class="del_item" @click="triggerDelItem(item,index)">删除</view>
</view>
</view>
</view>
然后再看看我们的js代码:
export default {
data(){
return {
list:[
{id:"001",timebName:"时间段",startTime:"10:00",endTime:"14:00",moveX:0},
{id:"002",timebName:"时间段",startTime:"9:00",endTime:"15:00",moveX:0},
{id:"003",timebName:"时间段",startTime:"11:00",endTime:"18:00",moveX:0},
],
curLang: Vue.config.lang,
curTimeItem:{
startTime:"",
endTime:"",
},
hours: Array.from({ length: 24 }, (_, i) => i),
minutes: Array.from({ length: 60 }, (_, i) => i),
timeValue: [8, 30],
isShowPicker:false,
delBtnWidth: 60,
startX:0,
moveX:0,
visible:false
}
},
methods:{
i18nCast,
drawStart(e){
this.startX=e.touches[0].clientX;
console.log("this.startx",this.startX)
},
drawMove(e,item){
item.moveX=e.touches[0].clientX-this.startX;
if(item.moveX>=0){
item.moveX=0
}else{
if(item.moveX<=-this.delBtnWidth/2){
item.moveX=-this.delBtnWidth
}
}
},
drawEnd(e,item){
if(item.moveX<0){
if(Math.abs(item.moveX)<this.delBtnWidth/2){
item.moveX=0
}else{
item.moveX=-this.delBtnWidth
}
}
console.log("t抬起:",item.moveX)
},
}
最后是我们的css代码:
、
.time_item{
display: flex;
padding: 3.2vw 0 3.2vw 5.3333vw;;
box-sizing: border-box;
position: relative;
background: #fff;
transition: all 0.2s ease-in;
.item_cont{
padding-right: 32vw;
height: 100%;
// width: calc(100% - 60px);
display: flex;
width: 100%;
.start_item,.end_item{
width: 50%;
}
.start_item_title,.end_item_title{
font-size: 3.7333vw;
font-style: normal;
font-weight: 400;
line-height: 5.3333vw;
}
}
.del_item{
width: 16vw;
height: 100%;
background-color: #FF5F3D;
color: white;
position: absolute;
top: 0;
right:-16vw;
font-size: 3.7333vw;
font-weight: 400;
line-height: 5.3333vw;
display: flex;
justify-content: center;
align-items: center;
}
}
当然我们也可以采用定位的方式实现这个效果:
<template>
<view class="SwipeActionBox">
<view v-for="item in csListArrl" :key="item.id" class="order-item" @touchstart="drawStart($event,item)"
@touchmove="drawMove($event,item)" @touchend="drawEnd($event,item)" :style="{right:`${item.right}px`}">
<view class="content">{{item.name}}</view>
<view class="remove" @click="delData(item)">注 销</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
csListArrl: [{
id: "001",
name: "测绘一测绘一测绘一测绘一",
right: 0
},
{
id: "002",
name: "测绘二测绘二测绘二测绘二测",
right: 0
},
{
id: "003",
name: "测绘三测绘三测绘三测绘三测",
right: 0
},
],
//左滑默认宽度
delBtnWidth: 160
}
},
onLoad() {
},
methods: {
//开始触摸滑动
drawStart(e, item) {
console.log("开始触发");
var touch = e.touches[0];
this.startX = touch.clientX;
},
//触摸滑动
drawMove(e, item) {
console.log("滑动");
var touch = e.touches[0];
var disX = touch.clientX-this.startX ;
console.log("disx:", disX)
if(disX<-this.delBtnWidth/2){
disX=-this.delBtnWidth
}
item.right = disX
}
},
//触摸滑动结束
drawEnd(e, item) {
console.log("滑动结束");
console.log("滑动结束--", e.currentTarget);
console.log("item:", item)
if(this.startX<0){
if(Math.abs(this.startX)<this.delBtnWidth/2){
this.startX=0
}else{
this.startX=-this.delBtnWidth
}
}
},
//删除方法
delData(item) {
console.log("删除")
uni.showModal({
title: '提示',
content: "确认注销该人员?",
success: function(res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
}
}
</script>
<style scoped>
.order-item {
width: 100%;
display: flex;
position: relative;
padding: 10px 0;
transition: all 0.2s ease-out;
}
.remove {
width: 80px;
height: 100%;
background-color: red;
color: white;
position: absolute;
top: 0;
right: -165px;
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
}
</style>