<template>
<div class="drag-list">
<ul class="drag-list-ul">
<li v-for="(item, index) in list"
:key="index"
@touchstart.prevent="onTouchStart($event,item)"
@touchmove.prevent="onTouchMove"
@touchend="onTouchEnd"
:class="{'drag': tarIndex === index, 'transition': tarIndex != -1}"
:style="{'transform': 'translate3d(0, ' + item.translateY + 'px, 0)'}"
>
<div class="left-icon-wrapper" :class="'pay_type_' + item.value">
<i class="icon left-icon" v-html="item.icon"></i>
</div>
<div class="drag-list-ul-li-cont">{{item.text}} <i class="icon" v-if="list.length > 1">&
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'DragList',
props: {
list: {
type: Array,
default: []
}
// listItem: {
// text: '',
// value: 'E',
// translateY: 0,
// icon: ''
// }
},
data(){
return {
delta: 0,
startY: 0,
tarIndex: -1,
moveIndex: 0,
direction: '',
tarH: 0
}
},
methods: {
onTouchStart(e, item) {
if(this.list.length <= 1) return;
const target = e.currentTarget;
this.delta = 0;
this.startY = e.pageY || e.touches[0].pageY;
this.tarH = target.clientHeight;
this.tarIndex = this.list.indexOf(item);
},
onTouchMove(e) {
if(this.list.length <= 1) return;
const target = e.currentTarget;
const nowY = e.pageY || e.touches[0].pageY;
this.delta = nowY - this.startY;
this.direction = this.delta < 0 ? 'up' : 'down';
target.style.transform = 'translate3d(0,' + this.delta + 'px, 0)';
this.moveIndex = this.getMoveIndex();
this.jostleOtherNode();
},
onTouchEnd() {
if(this.list.length <= 1) return;
this.updateList();
this.reset();
},
reset() {
this.delta = 0;
this.startY = 0;
this.tarIndex = -1;
this.moveIndex = 0;
},
getMoveIndex() {
// 计算向上或者向下移动的几个位置 moveIndex < 0 向上 > 0 向下
let moveIndex = Math.round( this.delta / this.tarH );
// 边界判断
const toIndex = this.tarIndex + moveIndex;
if(toIndex < 0) { // 向上越界
moveIndex = - this.tarIndex;
}else if(toIndex > this.list.length - 1) { // 向下越界
moveIndex = this.list.length - 1 - this.tarIndex;
}
return moveIndex;
},
jostleOtherNode() {
const index = this.tarIndex + this.moveIndex;
let start, end;
if(this.direction === 'up') {
this.list[index].translateY = (index === this.tarIndex) ? this.delta : this.tarH;
start = 0;
end = index;
}else {
this.list[index].translateY = (index === this.tarIndex) ? this.delta : -this.tarH;
start = index + 1;
end = this.list.length;
}
// 重置其他节点
for(let i = start; i < end; i++) {
if(this.list[i].translateY !== 0) {
this.list[i].translateY = 0;
}
}
},
updateList() {
const addIndex = this.direction === 'up' ?
this.tarIndex + this.moveIndex :
this.tarIndex + this.moveIndex + 1;
const deleteIndex = this.direction === 'up' ? this.tarIndex + 1 : this.tarIndex;
const value = this.list[this.tarIndex];
this.$emit('updateList',{addIndex,deleteIndex,value}); //通知父组件重新渲染
}
}
}
</script>