需求
最近开发一个聊天软件,需要用到左滑显示、右滑隐藏。如图:
本来打算自己写,但是又因为刚接触uniapp没有思路。所以我选择在网上参考一下大家的学习学习。
偶然翻到这篇文章后觉得写的简单易懂,所以就参考学习了这篇文章:
参考文章:uniapp上实现一个左滑显示删除按钮,右滑删除按钮消失
问题
但是也遇到了问题,因为列表是for循环出来的,所以在拖动一个项目的时候都会被拖动,于是就在原代码的基础上进行了修改:
html部分
<view class="list" v-for="(item,index) in list">
<view class="side-bar">
<!-- 拖动后显示的功能按钮 -->
</view>
<!-- 需要拖动的模块 -->
<view class="mask" @touchstart="touchS" @touchmove="touchM" @touchend="touchE" @click="clickList"
:data-index="index" :style="{left: item.leftStyle + 'rpx'}">
<view class="mask-img">
<image :src="'../../static/img/' + item.img" mode="widthFix"></image>
</view>
<view class="mask-con">
<view class="mask-top">
<view class="mask-title">{{ item.name }}</view>
<image class="mask-mdr" v-show="item.mdr" src="../../static/img/mdr.png" mode="widthFix">
</image>
<view class="mask-date">{{ item.date }}</view>
</view>
<view class="mask-bottom">
<view class="mask-text">{{ item.text }}</view>
<view class="mask-num">{{ item.num }}</view>
</view>
</view>
</view>
<view class="hr"></view>
</view>
:data-index=“index” 不能省略,因为后面会用到!
js部分
<script>
export default {
data() {
return {
delBtnWidth: 332,//拖动后显示部分的宽度
list: [{
img: '',
name: '',
mdr: false,
date: '2021/12/01',
text: '',
num: 99,
leftStyle: 0,//移动的距离
hiddenFlag: true,//左右移状态
startX: 0,
},
{
img: '',
name: '',
mdr: true,
date: '',
text: '',
num: 9,
leftStyle: 0,
hiddenFlag: true,
startX: 0,
}
]
}
},
onLoad() {
},
onShow() {
},
methods: {
// 遍历数组,清空列表的左移效果(其实这一块的效果不太满意,但是还是没想到最好的方式)
endActive() {
this.list.forEach((item, i) => {
item.leftStyle = 0;
})
},
// 点击列表之后清空左移效果
clickList() {
this.endActive()
},
// 开始移动时
touchS(e) {
const i = e.currentTarget.dataset.index;// 获取到当前移动元素的索引值
// startX记录开始移动的位置
if (e.touches.length === 1) {
this.list[i].startX = e.touches[0].clientX;
}
// hiddenFlag为true则是从右向左,为false则是从左向右
if (this.list[i].leftStyle === 0) {
this.list[i].hiddenFlag = true;
} else {
this.list[i].hiddenFlag = false;
}
},
touchM(e) {
this.endActive() // 开始移动后先清空左移效果再进行移动
if (e.touches.length === 1) {
//手指移动时水平方向位置
const moveX = e.touches[0].clientX;
const i = e.currentTarget.dataset.index;
this.moveFunc(moveX, i);
}
},
touchE(e) {
const i = e.currentTarget.dataset.index;
const { delBtnWidth } = this;
// 如果停止滑动的距离大于二分之一则直接弹出删除按钮,不然则left为0
if (-this.list[i].leftStyle > delBtnWidth / 2) {
this.list[i].leftStyle = -delBtnWidth;
} else {
this.list[i].leftStyle = 0;
}
},
moveFunc(moveX, i) {
// 原始位置向左,leftStyle为小于0;原始位置向右,leftStyle为大于0
// disX为相对最初位置的左右距离
// 大于0为向右,小于0为向左
const disX = moveX - this.list[i].startX;
const delBtnWidth = this.delBtnWidth;
let offsetNum = 0;
if (-disX >= delBtnWidth && this.list[i].leftStyle === -delBtnWidth) {
return;
}
// console.log(disX, this.hiddenFlag);
// this.hiddenFlag为true则是从左到右,则应该将container向左移动
// this.hiddenFlag为false则是从右向左,则应该将container向右移动
if (this.list[i].hiddenFlag) {
// 此时container为最右边,则应该将container向左移动
// disX大于0为相对原始位置的向右移动,则直接将offsetNum置为0
// 否则为向左移动,offsetNum为disX相反的值,判断是否超过设置的最大位置
if (disX == 0 || disX > 0) {
offsetNum = 0;
} else {
offsetNum = disX;
if (disX <= -delBtnWidth) {
//控制手指移动距离最大值为删除按钮的宽度
offsetNum = -delBtnWidth;
}
}
} else {
// 此时container为最左边,应该向右移动
// disX小于0为相对原始位置的向左移动,则直接将offsetNum置为-this.delBtnWidth
// 否则为相对原始位置的向右移动,此时应该将最大位置与向右位置的差值为此刻位置,判断是否为大于0
if (disX < 0) {
offsetNum = -this.delBtnWidth;
} else {
offsetNum = -this.delBtnWidth + disX;
if (offsetNum > 0) {
offsetNum = 0;
}
}
}
this.list[i].leftStyle = offsetNum;
}
}
}
</script>
原博主是将leftStyle: 0,startX: 0,hiddenFlag: true设置到了数组外,我是将每个数组都添加了这三个。
修改
touchS({ touches }) 修改成 ——> touchS(e)
if(touches.length === 1) { 修改成 ——> if (e.touches.length === 1) {
{touches}换成e是为了获取到当前移动元素的索引值:
const i = e.currentTarget.dataset.index;
获取到索引值后对数组内改项目对应字段进行修改,用下面两个片段举个栗子:
开始移动时:
touchS(e) {
const i = e.currentTarget.dataset.index;
// startX记录开始移动的位置
if (e.touches.length === 1) {
this.list[i].startX = e.touches[0].clientX;
}
// hiddenFlag为true则是从右向左,为false则是从左向右
if (this.list[i].leftStyle === 0) {
this.list[i].hiddenFlag = true;
} else {
this.list[i].hiddenFlag = false;
}
},
移动时将索引值传入moveFunc()方法
touchM(e) {
this.endActive()
if (e.touches.length === 1) {
//手指移动时水平方向位置
const moveX = e.touches[0].clientX;
const i = e.currentTarget.dataset.index;
this.moveFunc(moveX, i);
}
},
文中有链接我参考的原文,写的很好也很详细,也可以留言和我沟通。第一次写文章有写的不好的地方也可以和我指出~