You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带索引赋值的表格排序:Buefy与Sortable.js实现问询

实现Buefy表格结合Sortable.js的拖拽排序并更新order字段

我来帮你完成这个需求——用Sortable.js实现Buefy表格行的拖拽排序,并且在排序完成后自动更新数组中每个对象的order字段。下面是完整的实现方案和关键细节:


完整实现代码(Vue组件示例)

模板部分

<template>
  <b-table :data="ruta" :columns="columns" class="sortable-table">
    <!-- 添加拖拽手柄列,提升拖拽体验 -->
    <template #cell(drag)="{ row }">
      <span class="drag-handle">☰</span>
    </template>
  </b-table>
</template>

脚本部分

<script>
import Sortable from 'sortablejs';

export default {
  data() {
    return {
      // 你的数据源
      ruta: [
        { 'order': 1, 'id': 121 },
        { 'order': 2, 'id': 123 }
      ],
      // 表格列配置
      columns: [
        { field: 'drag', label: '', width: '50px', sortable: false },
        { field: 'order', label: '排序号', sortable: false },
        { field: 'id', label: 'ID', sortable: false }
      ],
      sortableInstance: null
    };
  },
  mounted() {
    // 获取Buefy表格的tbody元素
    const tbody = document.querySelector('.sortable-table tbody');
    if (tbody) {
      // 创建Sortable实例
      this.sortableInstance = Sortable.create(tbody, {
        handle: '.drag-handle', // 指定拖拽触发的元素
        animation: 150, // 添加拖拽动画,提升体验
        onEnd: (evt) => {
          this.handleSortEnd(evt);
        }
      });
    }
  },
  methods: {
    handleSortEnd(evt) {
      const { oldIndex, newIndex } = evt;
      const { ruta } = this;

      // 1. 调整数组的顺序,和表格行顺序保持一致
      const [movedItem] = ruta.splice(oldIndex, 1);
      ruta.splice(newIndex, 0, movedItem);

      // 2. 重新为每个对象的order字段赋值(从1开始递增)
      ruta.forEach((item, index) => {
        item.order = index + 1;
        // 如果是Vue2,若修改属性无响应,可改用Vue.set(item, 'order', index + 1)
      });
    }
  },
  beforeUnmount() {
    // 组件销毁前销毁Sortable实例,避免内存泄漏
    if (this.sortableInstance) {
      this.sortableInstance.destroy();
    }
  }
};
</script>

样式部分

<style scoped>
.drag-handle {
  cursor: grab;
  user-select: none;
  padding: 0 8px;
  color: #666;
}
.drag-handle:active {
  cursor: grabbing;
}
</style>

关键步骤解析

  1. Sortable实例初始化

    • 在组件mounted钩子中获取Buefy表格的tbody元素,这是Sortable需要绑定的目标容器
    • 通过handle指定拖拽手柄,避免用户点击表格其他区域误触发拖拽
  2. 拖拽结束后的数组调整

    • 使用数组的splice方法将拖拽的元素从旧位置移除,插入到新位置,确保数组顺序和表格行顺序同步
    • splice是Vue响应式数组方法,会自动触发表格的视图更新
  3. order字段重新赋值

    • 遍历调整后的数组,将每个元素的order设置为索引+1,保证排序号从1开始连续递增
    • 若使用Vue2,直接修改对象属性可能不触发响应式更新,此时可以用Vue.set(item, 'order', index + 1)替代
  4. 内存泄漏防范

    • 在组件beforeUnmount钩子中销毁Sortable实例,避免组件销毁后残留事件监听

自定义指令版本(可选)

如果你更倾向于用自定义指令封装Sortable逻辑,可以参考以下实现:

// 注册全局自定义指令
import Vue from 'vue';
import Sortable from 'sortablejs';

Vue.directive('sortable', {
  inserted(el, binding, vnode) {
    const options = binding.value || {};
    const sortable = Sortable.create(el, {
      ...options,
      onEnd: (evt) => {
        const data = vnode.context[binding.arg];
        // 调整数组顺序
        const [movedItem] = data.splice(evt.oldIndex, 1);
        data.splice(evt.newIndex, 0, movedItem);
        // 更新order字段
        data.forEach((item, index) => {
          item.order = index + 1;
        });
        // 执行用户传入的自定义onEnd逻辑(如果有的话)
        if (options.onEnd) options.onEnd(evt);
      }
    });
    // 将实例挂载到组件上下文,方便销毁
    vnode.context.sortableInstance = sortable;
  },
  unbind(el, binding, vnode) {
    if (vnode.context.sortableInstance) {
      vnode.context.sortableInstance.destroy();
    }
  }
});

在模板中使用:

<b-table :data="ruta" :columns="columns" v-sortable:ruta="{ handle: '.drag-handle' }">
  <!-- 拖拽手柄列 -->
</b-table>

这样就可以在多个组件中复用这个拖拽排序功能啦。

内容的提问来源于stack exchange,提问作者Piero Pajares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:21:48