前言
上篇我们写了,固定高度的拖拽,这篇我们将进行不固定高度的拖拽模块编写完成。
开始
一、初始化
我们在list数组里面增加一个data的动态数组,这样可以动态改变元素的高度。
当前元素y = 上一个元素的高度
<template>
<view style="height: 100%;">
<movable-area :style="{'width': '100%', 'height': allHeight + 'px'}">
<movable-view
v-for="(item, index) in list"
:key="item.id"
:x="0"
:y="item.y"
:style="{'height': item.itemHeight + 'px', 'width': '100%',}"
direction="all"
@touchstart="handleDragStart(index)"
@change="handleMoving(index, $event)"
@touchend="handleDragEnd"
class="movable-view"
>
<!-- 这里可以放置步骤的详细内容 -->
<view style="background-color: aqua; padding: 20rpx 0; margin: 10rpx 0;">
<view v-for="(d_item, d_key) in item['data']" :key="d_key">{{ d_item.name }}</view>
</view>
</movable-view>
</movable-area>
</view>
</template>
<script>
export default {
data() {
return {
list: [],
allHeight: 0,
};
},
created() {
// 初始化 === 当前y=上一个元素高度(索引为0的y=0)
this.list = [
{
id: 0,
itemHeight: 100,
y: 0,
key: Math.random() + 0,
data: [
{
name: '测试0-1'
},
{
name: '测试0-2'
}
]
},
{
id: 1,
itemHeight: 50,
y: 100,
key: Math.random() + 1,
data: [
{
name: '测试1-1'
}
]
},
{
id: 2,
itemHeight: 50,
y: 150,
key: Math.random() + 2,
data: [
{
name: '测试2-1'
}
]
},
{
id: 3,
itemHeight: 200,
y: 200,
key: Math.random() + 3,
data: [
{
name: '测试3-1'
},
{
name: '测试3-2'
},
{
name: '测试3-3'
},
{
name: '测试3-4'
}
]
},
]
},
methods: {
},
};
</script>
<style>
.movable-area {
}
.movable-view {
}
</style>
二、拖拽实现
y是高度累加,通过ref获取元素高度
<template>
<view style="height: 100%;">
<movable-area :style="{'width': '100%', 'height': allHeight + 'px'}">
<movable-view v-for="(item, index) in list" :key="item.id" :x="0" :y="item.y"
:style="{'height': item.itemHeight + 'px', 'width': '100%', 'background-color': '#fff'}" direction="all"
@touchstart="handleDragStart(index)" @change="handleMoving(index, $event)" @touchend="handleDragEnd"
class="movable-view">
<!-- 这里可以放置步骤的详细内容 -->
<view ref="itemRef" style="background-color: aqua; height: 100%; margin: 10rpx 0;">
<view v-for="(d_item, d_key) in item['data']" :key="d_key">{{ d_item.name }}</view>
</view>
</movable-view>
</movable-area>
</view>
</template>
<script>
export default {
data() {
return {
list: [],
cloneList: [],
activeIndex: -1, // 选中
oldIndex: -1,
moveToIndex: -1, // 移动
allHeight: 1200,
};
},
mounted() {
// console.log("===itemRef===", this.$refs.itemRef);
// if (this.$refs.itemRef) {
// this.$refs.itemRef.forEach((item) => {
// console.log(item.$el.clientHeight)
// });
// }
},
created() {
// 1.通过ref获取元素高度,并进行计算y轴
// 2.拖拽时,更换位置(重新计算-高度累积计算)
// 注意点(总高度不够时,会乱排序)
// 初始化
this.list = [{
id: 0,
y: 0,
itemHeight: 100,
data: [{
name: '测试0-1'
},
{
name: '测试0-2'
}
]
},
{
id: 1,
y: 100,
itemHeight: 50,
data: [{
name: '测试1-1'
}]
},
{
id: 2,
y: 150,
itemHeight: 50,
data: [{
name: '测试2-1'
}]
},
{
id: 3,
y: 200,
itemHeight: 200,
data: [{
name: '测试3-1'
},
{
name: '测试3-2'
},
{
name: '测试3-3'
},
{
name: '测试3-4'
}
]
},
];
this.cloneList = this.deepCopy(this.list);
},
methods: {
deepCopy(source) {
return JSON.parse(JSON.stringify(source));
},
// 拖拽开始
handleDragStart(index) {
this.activeIndex = index;
this.oldIndex = index;
},
handleMoving(index, e) {
if (e.detail.source !== 'touch') return;
const {x, y} = e.detail;
let itemHeight = this.list[index]['itemHeight'];
const currentY = Math.floor((y + itemHeight / 2) / itemHeight);
this.moveToIndex = Math.min(currentY, this.list.length - 1);
// console.log("===this.moveToIndex===", this.moveToIndex);
},
handleDragEnd(e) {
console.log("=====拖拽结束============");
if (this.moveToIndex !== -1 && this.activeIndex !== -1 && this.moveToIndex !== this.activeIndex) {
// console.log("===选中目标activeIndex===", this.list[this.activeIndex]);
// console.log("===移动目标moveToIndex===", this.list[this.moveToIndex]);
// 交互位置
this.cloneList.splice(this.moveToIndex, 0, ...this.cloneList.splice(this.activeIndex, 1));
// 计算y轴
this.cloneList.forEach((item) => {
item.y = currentY;
currentY += item.itemHeight;
});
this.list = this.cloneList
}
this.activeIndex = -1;
this.oldIndex = -1;
this.moveToIndex = -1;
},
},
};
</script>
<style>
.movable-area {}
.movable-view {}
</style>