美文网首页
自己封装的 Vue拖拽排序组件。是两个项目对调位置

自己封装的 Vue拖拽排序组件。是两个项目对调位置

作者: 芸芸众生ing | 来源:发表于2019-10-05 15:31 被阅读0次

使用方法:
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>

相关文章

网友评论

      本文标题:自己封装的 Vue拖拽排序组件。是两个项目对调位置

      本文链接:https://www.haomeiwen.com/subject/xwzepctx.html