网站/小程序/APP个性化定制开发,二开,改版等服务,加扣:8582-36016

    这篇文章主要为大家详细介绍了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, // 当前列表元素之间是否支持交换位置
    }



    评论 0

    暂无评论
    0
    0
    0
    立即
    投稿
    发表
    评论
    返回
    顶部