好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

vue实现拖拽排序效果

本文实例为大家分享了vue实现拖拽排序效果的具体代码,供大家参考,具体内容如下

效果预览

组件 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("缺少配置关联名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("缺少配置关联属性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>

参数说明

list: 渲染列表
config: {
    name: '', // 跨列表关联名,跨列表拖拽时必传
    push: true, // 当前列表是否支持从其他列表push元素进来
    pull: true, // 将当前列表的某个元素拖拽并添加到其他列表里,该元素是否从当前列表移除
    exchange: true, // 当前列表元素之间是否支持交换位置
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

查看更多关于vue实现拖拽排序效果的详细内容...

  阅读:37次