使用方法:
1、在需要的组件内引用
<template>
<wDrag v-model="arr" :key="keyUpdate">
<template slot="body">
<div v-for="v in arr" :key="v">{{v}} - 可拖拽</div>
</template>
</wDrag>
</template>
<script>
export default {
components: {
wDrag: () => import("./drag.vue")
},
data() {
return {
arr: [1, 2, 3, 4, 5],
keyUpdate: 0 // 动态请求数据加载的时候,需要使用 key的特性 重新渲染该组件,所以需要数据请求成功后,重新赋值一次
};
},
created() {
setTimeout(() => {
this.arr = ["q", "b", "c", "d", "e", "f"];
this.keyUpdate = Math.random(); //模拟请求数据后,一定要更新这个key
}, 2000);
}
};
</script>
2、 复制下面的代码保存为vue组件;供其他组件使用
<template>
<div class="drag" ref="drag" id="drag">
<slot name="body"></slot>
</div>
</template>
<script>
export default {
mounted() {
this.onDrag();
},
watch: {
value(a) {
if (!a) return;
this.$nextTick(() => {
this.onDrag();
});
}
},
props: {
value: {
type: Array,
default() {
return [];
},
required: true
},
type: {
// 使用这个默认值即可
type: String,
default: "all"
}
},
methods: {
onDrag() {
let that = this;
class drag {
constructor(ele, dataArray) {
this.children = [...ele];
if (that.type !== "all") {
this.children.pop();
}
this.dataArray = dataArray;
this.toIndex = null;
this.currentIndex = null;
this.currentNode = null;
this.move = {
x: 0,
y: 0,
move: false
};
this.init();
}
init() {
this.children.forEach((item, i) => {
item.onmousedown = this.onMouseDown.bind(this);
item.classList.add("list-complete-item");
});
}
onMouseDown(e) {
this.currentNode = this.getNode(
e,
".list-complete-item"
)[0];
this.currentNode.setAttribute("draggable", "true");
this.currentNode.ondragend = this.onMouseUp.bind(this);
this.currentNode.ondragstart = this.onMouseStart.bind(this);
}
onMouseStart(e) {
e.dataTransfer.setData("who", e.target);
this.children.forEach((v, i) => {
if (v == this.currentNode) this.currentIndex = i;
v.ondragenter = e => {
v.classList.add("current");
this.toIndex = this.children.findIndex(k => v == k);
};
v.ondragleave = () => {
v.classList.remove("current");
};
});
}
onMouseUp(e) {
let a = this.dataArray[this.currentIndex];
let b = this.dataArray[this.toIndex];
if (a == b) return;
this.dataArray.splice(this.toIndex, 1, a);
this.dataArray.splice(this.currentIndex, 1, b);
this.currentNode.removeAttribute("draggable");
that.$emit("input", this.dataArray);
that.$emit(
"change",
{
current: {
index: this.currentIndex,
data: a
},
target: {
index: this.toIndex,
data: b
}
},
that.value
);
}
getNode(e, select) {
var a = e.path || e.composedPath();
let sele = "";
if (select) {
/^[a-zA-Z]+$/g.test(select)
? (sele = "target")
: (sele = select.slice(0, 1));
switch (sele) {
case ".":
a = [...a].filter(k => {
if (
k.getAttribute &&
k.getAttribute("class")
) {
return (
k
.getAttribute("class")
.indexOf(select.slice(1)) != -1
);
}
});
break;
case "#":
a = [...a].filter(k => {
if (k.id) {
return k.id == select.slice(1);
}
});
break;
case "target":
a = [...a].filter(k => {
if (k.nodeName) {
return (
k.nodeName.toLowerCase() ==
select.toLowerCase()
);
}
});
break;
default:
a = select + "is not defined";
}
} else {
a = [...a].filter(k => {
if ([...e.currentTarget.children].indexOf(k) >= 0)
return true;
})[0];
}
return a;
}
}
let node = this.$refs["drag"].children;
new drag(node, this.value);
}
}
};
</script>
<style>
.slide-item {
transition: all 0.5s ease-out;
}
.list-complete-item {
cursor: move;
transition: all 0.2s;
}
.current {
box-shadow: 0 0 20px #000;
background: #f1f1f1;
transition: all 0.2s;
}
</style>
网友评论