vue實(shí)現(xiàn)拖拽排序效果
本文實(shí)例為大家分享了vue實(shí)現(xiàn)拖拽排序效果的具體代碼,供大家參考,具體內(nèi)容如下
效果預(yù)覽

組件 drag.vue
<template>
? <TransitionGroup name="group-list" tag="ul">
? ? <li
? ? ? v-for="(item, index) in list"
? ? ? :key="item.name"
? ? ? :draggable="item.draggable"
? ? ? :class="[
? ? ? ? 'list-item',
? ? ? ? {
? ? ? ? ? 'is-dragover':
? ? ? ? ? ? index === dropIndex && item.draggable && config.exchange,
? ? ? ? },
? ? ? ]"
? ? ? @dragstart="onDragstart($event, index)"
? ? ? @dragenter="onDragenter(index)"
? ? ? @dragover.prevent="onDragover(index)"
? ? ? @dragleave="onDragleave"
? ? ? @dragend="onDragend"
? ? ? @drop="onDrop"
? ? >
? ? ? <slot :item="item" />
? ? </li>
? </TransitionGroup>
</template>
<script>
export default {
? name: "Draggable",
? props: {
? ? list: {
? ? ? type: Array,
? ? ? default: () => [],
? ? },
? ? config: {
? ? ? type: Object,
? ? ? default: () => ({
? ? ? ? name: "",
? ? ? ? push: true,
? ? ? ? pull: true,
? ? ? ? exchange: true,
? ? ? }),
? ? },
? },
? data() {
? ? return {
? ? ? dragIndex: null,
? ? ? dropIndex: null,
? ? };
? },
? computed: {
? ? isPush() {
? ? ? const { dropIndex, dragIndex } = this;
? ? ? return dropIndex !== null && dragIndex === null;
? ? },
? ? isExchange() {
? ? ? const { dropIndex, dragIndex } = this;
? ? ? return dragIndex !== null && dropIndex !== null;
? ? },
? ? pushCbName() {
? ? ? const {
? ? ? ? config: { name },
? ? ? } = this;
? ? ? return `${name}-push-callback`;
? ? },
? },
? methods: {
? ? onDragstart(e, i) {
? ? ? const {
? ? ? ? list,
? ? ? ? config: { name },
? ? ? ? transferData,
? ? ? } = this;
? ? ? this.dragIndex = i;
? ? ? if (name) {
? ? ? ? transferData({ e, key: name, type: "set", data: list[i] });
? ? ? } else {
? ? ? ? throw new Error("缺少配置關(guān)聯(lián)名name");
? ? ? }
? ? ? this.$emit("drag-start", i);
? ? },
? ? onDragenter(i) {
? ? ? this.dropIndex = i;
? ? ? this.$emit("drag-enter", i);
? ? },
? ? onDragover(i) {
? ? ? const { dragIndex, dropIndex } = this;
? ? ? if (i === dragIndex || i === dropIndex) return;
? ? ? this.dropIndex = i;
? ? ? this.$emit("drag-over", i);
? ? },
? ? onDragleave() {
? ? ? this.dropIndex = null;
? ? },
? ? onDrop(e) {
? ? ? const {
? ? ? ? list,
? ? ? ? dropIndex,
? ? ? ? dragIndex,
? ? ? ? config: { name, push: enablePush, exchange },
? ? ? ? isPush,
? ? ? ? isExchange,
? ? ? ? pushCbName,
? ? ? ? storage,
? ? ? ? resetIndex,
? ? ? ? transferData,
? ? ? } = this;
? ? ? if (dropIndex === dragIndex || !exchange) return;
? ? ? if (isPush) {
? ? ? ? if (!enablePush) {
? ? ? ? ? resetIndex();
? ? ? ? ? return;
? ? ? ? }
? ? ? ? if (name) {
? ? ? ? ? list.splice(
? ? ? ? ? ? dropIndex,
? ? ? ? ? ? 0,
? ? ? ? ? ? transferData({ e, key: name, type: "get" })
? ? ? ? ? );
? ? ? ? ? storage("set", pushCbName, true);
? ? ? ? } else {
? ? ? ? ? resetIndex();
? ? ? ? ? throw new Error("缺少配置關(guān)聯(lián)屬性name");
? ? ? ? }
? ? ? ? resetIndex();
? ? ? ? return;
? ? ? }
? ? ? if (isExchange) {
? ? ? ? const drapItem = list[dragIndex];
? ? ? ? const dropItem = list[dropIndex];
? ? ? ? list.splice(dropIndex, 1, drapItem);
? ? ? ? list.splice(dragIndex, 1, dropItem);
? ? ? }
? ? ? resetIndex();
? ? },
? ? onDragend() {
? ? ? const {
? ? ? ? list,
? ? ? ? dragIndex,
? ? ? ? config: { pull: enablePull },
? ? ? ? pushCbName,
? ? ? ? storage,
? ? ? ? resetIndex,
? ? ? } = this;
? ? ? if (enablePull) {
? ? ? ? const isPushSuccess = storage("get", pushCbName);
? ? ? ? if (isPushSuccess) {
? ? ? ? ? list.splice(dragIndex, 1);
? ? ? ? ? storage("remove", pushCbName);
? ? ? ? }
? ? ? }
? ? ? resetIndex();
? ? ? this.$emit("drag-end");
? ? },
? ? storage(type, key, value) {
? ? ? return {
? ? ? ? get() {
? ? ? ? ? return JSON.parse(localStorage.getItem(key));
? ? ? ? },
? ? ? ? set() {
? ? ? ? ? localStorage.setItem(key, JSON.stringify(value));
? ? ? ? },
? ? ? ? remove() {
? ? ? ? ? localStorage.removeItem(key);
? ? ? ? },
? ? ? }[type]();
? ? },
? ? resetIndex() {
? ? ? this.dropIndex = null;
? ? ? this.dragIndex = null;
? ? },
? ? transferData({ e, key, type, data } = {}) {
? ? ? if (type === "get") {
? ? ? ? return JSON.parse(e.dataTransfer.getData(`${key}-drag-key`));
? ? ? }
? ? ? if (type === "set") {
? ? ? ? e.dataTransfer.setData(`${key}-drag-key`, JSON.stringify(data));
? ? ? }
? ? },
? },
};
</script>
<style ?scoped>
.list-item {
? list-style: none;
? position: relative;
? margin-bottom: 10px;
? border-radius: 4px;
? padding: 4px;
? background-color: #fff;
? cursor: move;
}
.list-item.is-dragover::before {
? content: "";
? position: absolute;
? bottom: -4px;
? left: 0;
? width: 100%;
? height: 4px;
? background-color: #0c6bc9;
}
.list-item.is-dragover::after {
? content: "";
? position: absolute;
? bottom: -8px;
? left: -6px;
? border: 3px solid #0c6bc9;
? border-radius: 50%;
? width: 6px;
? height: 6px;
? background-color: #fff;
}
.group-list-move {
? transition: transform 0.8s;
}
</style>使用范例
index.vue
<template>
? <div class="dragBox">
? ? <Drag style="width: 200px" :list="list1" :config="config1">
? ? ? <template v-slot="{ item }">
? ? ? ? <div class="item">
? ? ? ? ? {{ item.name }}
? ? ? ? </div>
? ? ? </template>
? ? </Drag>
? ? <Drag style="width: 200px" :list="list2" :config="config2">
? ? ? <template v-slot="{ item }">
? ? ? ? <div class="item">
? ? ? ? ? {{ item.name }}
? ? ? ? </div>
? ? ? </template>
? ? </Drag>
? </div>
</template>
<script>
import Drag from "./drag.vue";
export default {
? components: {
? ? Drag,
? },
? data() {
? ? return {
? ? ? list1: new Array(10).fill(0).map((_, i) => ({
? ? ? ? name: `列表1 - ${i + 1}`,
? ? ? ? draggable: true,
? ? ? })),
? ? ? config1: {
? ? ? ? name: "test",
? ? ? ? push: true,
? ? ? ? pull: true,
? ? ? ? exchange: true,
? ? ? },
? ? ? list2: new Array(10).fill(0).map((_, i) => ({
? ? ? ? name: `列表2 - ${i + 1}`,
? ? ? ? draggable: true,
? ? ? })),
? ? ? config2: {
? ? ? ? name: "test",
? ? ? ? push: true,
? ? ? ? pull: true,
? ? ? ? exchange: true,
? ? ? },
? ? };
? },
};
</script>
<style ?scoped>
.dragBox {
? display: flex;
? justify-content: center;
}
.item {
? border: 1px solid #ccc;
? width: 200px;
? height: 30px;
? text-align: center;
}
</style>參數(shù)說(shuō)明
list: 渲染列表
config: {
name: '', // 跨列表關(guān)聯(lián)名,跨列表拖拽時(shí)必傳
push: true, // 當(dāng)前列表是否支持從其他列表push元素進(jìn)來(lái)
pull: true, // 將當(dāng)前列表的某個(gè)元素拖拽并添加到其他列表里,該元素是否從當(dāng)前列表移除
exchange: true, // 當(dāng)前列表元素之間是否支持交換位置
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- vuedraggable+element ui實(shí)現(xiàn)頁(yè)面控件拖拽排序效果
- vue拖拽排序插件vuedraggable使用方法詳解
- 利用Vue-draggable組件實(shí)現(xiàn)Vue項(xiàng)目中表格內(nèi)容的拖拽排序
- 基于Vue實(shí)現(xiàn)平滑過(guò)渡的拖拽排序功能
- vue實(shí)現(xiàn)列表拖拽排序的功能
- vue.draggable實(shí)現(xiàn)表格拖拽排序效果
- vue 使用 sortable 實(shí)現(xiàn) el-table 拖拽排序功能
- antdesign-vue結(jié)合sortablejs實(shí)現(xiàn)兩個(gè)table相互拖拽排序功能
- Vue?基于?vuedraggable?實(shí)現(xiàn)選中、拖拽、排序效果
- vue拖拽組件 vuedraggable API options實(shí)現(xiàn)盒子之間相互拖拽排序
相關(guān)文章
vue.js實(shí)現(xiàn)只能輸入數(shù)字的輸入框
這篇文章主要為大家詳細(xì)介紹了vue.js實(shí)現(xiàn)只能輸入數(shù)字的輸入框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
bootstrap vue.js實(shí)現(xiàn)tab效果
這篇文章主要為大家詳細(xì)介紹了bootstrap vue.js實(shí)現(xiàn)tab效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
VUE div click無(wú)效的問(wèn)題及解決
這篇文章主要介紹了VUE div click無(wú)效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
利用Vue的v-for和v-bind實(shí)現(xiàn)列表顏色切換
這篇文章主要介紹了利用Vue的v-for和v-bind實(shí)現(xiàn)列表顏色切換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
axios二次封裝的詳細(xì)過(guò)程與跨域問(wèn)題
通常我們的項(xiàng)目會(huì)越做越大,頁(yè)面也會(huì)越來(lái)越多,隨之而來(lái)的是接口數(shù)量的增加,api統(tǒng)一管理,不管接口有多少,所有的接口都可以非常清晰,容易維護(hù),下面這篇文章主要給大家介紹了關(guān)于axios二次封裝的詳細(xì)過(guò)程與跨域問(wèn)題的相關(guān)資料,需要的朋友可以參考下2022-09-09
記錄一個(gè)van-list不斷onLoad加載的坑及解決
這篇文章主要介紹了記錄一個(gè)van-list不斷onLoad加載的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
vue-cli-service?build?自定義參數(shù)方式
這篇文章主要介紹了vue-cli-service?build?自定義參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10

