仿qq的可左右滑动ListView
<template>
<div class="order-list">
<div class="order-part" :style="getRightDistance(index)" v-for="(order, index) in orderList" :key="index" @touchstart="touchstart(index)" @touchmove="touchmove" @touchend="touchend">
<div class="dialect">
<div class="head">
<div class="title">
<span>采购单号 {{ order.purchaseno }}</span>
</div>
<div class="status-name">
<span :class="getStatusSymbol(order.status)">{{ order.statusName }}</span>
</div>
</div>
<div class="exactly" @click="goOrderDetail(index)">
<div class="present">
<div class="dare">
<span class="label">供应商编号:</span>
<span class="value">{{ order.suppliercode }}</span>
</div>
<div class="dare">
<span class="label">供应商名称:</span>
<span class="value">{{ order.supplierName }}</span>
</div>
<div class="dare">
<span class="label">类型:</span>
<span class="value">{{ order.kindName }}</span>
</div>
</div>
<div class="amaze">
<van-icon class="item-arrow" name="arrow" color="#969799" />
</div>
</div>
</div>
<div class="hide-btn">
<span @click="generateWarehouse(order)" class="def">生成入库通知单</span>
<span @click="deletePurchase(order)" class="danger">删除</span>
</div>
</div>
</div>
</template>
<script>
import { Icon } from "vant";
export default {
props: {
orderList: {
type: Array,
required: true
}
},
data() {
return {
startX: 0,
currentX: 0,
deltaX: 0,
curIndex: 0,
rights: [],
isMove: false
}
},
created() {
this.loadRights();
},
components: {
[Icon.name]: Icon
},
methods: {
loadRights() {
for(let i = 0; i < this.orderList.length; i++) {
this.$set(this.rights, i, 0)
}
},
getRightDistance(index) {
let dist = 0;
if (this.curIndex === index) {
dist = this.rights[this.curIndex];
}
return { 'right': dist + 'px', 'transition': this.isMove ? '' : 'all .3s' }
},
getStatusSymbol(status) {
if (status == "0") {
return "warning";
} else if (status == "2") {
return "def";
} else {
return "primary";
}
},
goOrderDetail(index) {
this.$emit("goOrderDetail", index);
},
touchstart(index) {
this.curIndex = index;
// 获取触摸开始时的 X 坐标
this.startX = event.touches[0].clientX;
},
touchmove(event) {
this.isMove = true;
// 获取触摸移动时的 X 坐标
this.currentX = event.touches[0].clientX;
// 计算滑动的距离
this.deltaX = this.currentX - this.startX;
if (this.deltaX < 0) {
this.$set(this.rights, this.curIndex, -this.deltaX);
} else if (this.rights[this.curIndex] > 30) {
this.$set(this.rights, this.curIndex, 250 - (this.deltaX));
}
},
touchend() {
if (Math.abs(this.deltaX) > 30) {
// 向右滑动
if (this.deltaX > 0) {
setTimeout(() => {
this.setRights(0)
});
}
// 向左滑动
if (this.deltaX < 0) {
setTimeout(() => {
this.setRights(250)
});
}
} else {
this.$set(this.rights, this.curIndex, 0);
}
this.deltaX = 0;
this.isMove = false;
},
setRights(num) {
for(let i = 0; i < this.orderList.length; i++) {
this.$set(this.rights, i, 0);
}
this.$set(this.rights, this.curIndex, num);
},
generateWarehouse(order) {
this.setRights(0);
this.$emit('generateWarehouse', order);
},
deletePurchase(order) {
this.setRights(0);
this.$emit('deletePurchase', order);
}
}
};
</script>
<style scoped>
.order-list {
width: 100%;
}
.order-part {
position: relative;
right: 0;
transition: all .3s;
width: calc(100% + 250px);
display: flex;
border-bottom: 1px solid #eee;
background-color: #fff;
}
.dialect {
width: 100%;
}
.order-part:first-child {
margin-top: 0;
}
.head {
padding: 10px 8px 0 8px;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
}
.head .title {
font-size: 14px;
}
.status-name span {
padding: 2px 4px;
font-size: 12px;
}
.warning {
border-radius: 4px;
color: #fdcca1;
border: 1px solid #fdcca1;
background-color: #fef2e8;
}
.primary {
border-radius: 4px;
color: #a3ccf8;
border: 1px solid #a3ccf8;
background-color: #e9f2fd;
}
.def {
color: #f4f4f4;
}
.exactly {
padding: 8px 8px 2px 8px;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
}
.dare {
font-size: 12px;
color: #969799;
margin-bottom: 6px;
}
.hide-btn {
display: flex;
}
.def, .danger {
color: #fff;
display: flex;
align-items: center;
justify-content: center;
}
.def {
width: 150px;
background-color: #1485EF;
}
.danger {
width: 100px;
background-color: #FA5251;
}
</style>