在 Vue 2 中实现可拖拽排序指令:v-sortable

在 Vue 2 中实现可拖拽排序指令:v-sortable

在开发过程中,我们经常需要实现元素的拖拽排序功能。本文将详细介绍如何在 Vue 2 中创建一个自定义指令 v-sortable,使元素可以拖拽并交换位置,同时更新数据的位置。

自定义指令 v-sortable

首先,我们需要创建一个自定义指令 v-sortable,它使元素可拖动并处理拖放事件。

1. 创建自定义指令 sortable.js

// directives/sortable.js
export default {
  bind(el, binding, vnode) {
    el.draggable = true;

    el.addEventListener('dragstart', (event) => {
      event.dataTransfer.setData('text/plain', binding.value);
      el.classList.add('dragging');
    });

    el.addEventListener('dragend', () => {
      el.classList.remove('dragging');
    });

    el.addEventListener('dragover', (event) => {
      event.preventDefault();
    });

    el.addEventListener('drop', (event) => {
      event.preventDefault();
      const draggedIndex = event.dataTransfer.getData('text/plain');
      const droppedIndex = binding.value;

      console.log('Drag Drop Event: ', { draggedIndex, droppedIndex });
      vnode.context.handleDrop({ draggedIndex, droppedIndex });
    });
  }
};

2. 在组件中使用自定义指令

接下来,在你的 Vue 组件中使用这个自定义指令,并处理 handleDrop 方法以更新数据的位置。

<template>
  <div>
    <ul>
      <li
        v-for="(item, index) in items"
        :key="item.id"
        v-sortable="index"
        :class="{ dragging: draggingIndex === index }"
        @dragstart="setDraggingIndex(index)"
        @dragend="clearDraggingIndex"
      >
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>

<script>
import sortable from './directives/sortable';

export default {
  directives: {
    sortable
  },
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' }
      ],
      draggingIndex: null
    };
  },
  methods: {
    handleDrop({ draggedIndex, droppedIndex }) {
      console.log('Handle Drop Event: ', { draggedIndex, droppedIndex });

      const draggedItem = this.items[draggedIndex];
      this.items.splice(draggedIndex, 1);
      this.items.splice(droppedIndex, 0, draggedItem);
    },
    setDraggingIndex(index) {
      this.draggingIndex = index;
    },
    clearDraggingIndex() {
      this.draggingIndex = null;
    }
  }
};
</script>

<style scoped>
li {
  list-style: none;
  padding: 10px;
  margin: 5px;
  border: 1px solid #ccc;
  cursor: move;
}

li.dragging {
  opacity: 0.5;
  background-color: #ddd;
}
</style>

3. 解释

  • 指令部分
    • drop 事件处理函数中,直接调用 vnode.context.handleDrop,确保处理函数在当前组件上下文中被正确执行。
  • 组件部分
    • 使用 v-sortable="index"index 传递给指令。
    • handleDrop 方法中处理拖拽事件,更新数据的位置。

4. 调试与验证

  1. 验证事件触发
    • drop 事件处理函数中添加 console.log 语句,确保事件数据传递正确。
  2. 验证事件监听器
    • handleDrop 方法中添加 console.log 语句,确保方法被正确调用。
  3. 验证事件绑定
    • 确保事件监听器绑定在正确的元素上,检查组件模板,确保 @item-dropped="handleDrop" 确实存在于每个 li 元素中。

通过这些步骤,你可以验证事件是否正确触发并被监听,从而实现 Vue 2 中的拖拽排序功能。

结语

本文详细介绍了如何在 Vue 2 中实现一个可拖拽排序的自定义指令 v-sortable,通过处理拖拽事件来实现元素位置的交换和数据更新。希望本文能对你的开发有所帮助。

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
实现el-tab-pane拖拽排序的步骤如下: 1. 安装sortablejs和@vue/composition-api ``` npm install sortablejs @vue/composition-api --save ``` 2. 在Vue组件导入Sortable和reactive ```javascript import Sortable from 'sortablejs'; import { reactive } from '@vue/composition-api'; ``` 3. 创建一个响应式对象来存储tab列表 ```javascript const tabs = reactive({ list: [ { label: 'Tab 1', content: 'Content of Tab 1' }, { label: 'Tab 2', content: 'Content of Tab 2' }, { label: 'Tab 3', content: 'Content of Tab 3' } ] }); ``` 4. 在页面使用el-tabs和el-tab-pane组件来展示tab列表,并使用v-for指令循环展示tab列表 ```html <el-tabs v-model="activeTab"> <el-tab-pane v-for="(tab, index) in tabs.list" :key="index" :label="tab.label"> {{ tab.content }} </el-tab-pane> </el-tabs> ``` 5. 在mounted钩子函数使用Sortable创建可拖拽的tab列表,并监听其排序事件 ```javascript mounted() { let el = this.$el.querySelector('.el-tabs__nav-wrap'); new Sortable(el, { animation: 150, onEnd: (evt) => { let fromIndex = evt.oldIndex; let toIndex = evt.newIndex; tabs.list.splice(toIndex, 0, tabs.list.splice(fromIndex, 1)[0]); } }); } ``` 6. 完成后,你就可以在页面上看到一个可拖拽排序的tab列表了。 完整代码如下: ```html <template> <el-tabs v-model="activeTab"> <el-tab-pane v-for="(tab, index) in tabs.list" :key="index" :label="tab.label"> {{ tab.content }} </el-tab-pane> </el-tabs> </template> <script> import Sortable from 'sortablejs'; import { reactive } from '@vue/composition-api'; export default { name: 'SortableTabs', setup() { const tabs = reactive({ list: [ { label: 'Tab 1', content: 'Content of Tab 1' }, { label: 'Tab 2', content: 'Content of Tab 2' }, { label: 'Tab 3', content: 'Content of Tab 3' } ] }); return { tabs }; }, mounted() { let el = this.$el.querySelector('.el-tabs__nav-wrap'); new Sortable(el, { animation: 150, onEnd: (evt) => { let fromIndex = evt.oldIndex; let toIndex = evt.newIndex; this.tabs.list.splice(toIndex, 0, this.tabs.list.splice(fromIndex, 1)[0]); } }); } }; </script> ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值