引入SortableJS实现elementUItable拖动效果

背景

目前elmenetUI的表格是不支持拖动的,但表格行拖动要求往往比较常见。通过引入sortableJS可以方便的让elementUI组件中的table支持拖动效果。

网上大部分方案如下:

  • SortableJS + 原生table
  • SortableJS + 原生table + elementUI样式
  • 使用vueDraggable组件:https://github.com/SortableJS/Vue.Draggable

直接操作elementUI的table组件较少,记录一下。

实施方案

  • 引入SortableJS

    1
    npm install sortableJS --save
  • 创建表格组件,需要注意的是,必须设置row-key属性,否则在拖动展示时,会变成乱序

    • template部分

      1
      2
      3
      4
      5
      <el-table row-key="id" :data="tableData" style="width: 100%">
      <el-table-column prop="date" label="日期" width="180"></el-table-column>
      <el-table-column prop="name" label="姓名" width="180"></el-table-column>
      <el-table-column prop="address" label="地址"></el-table-column>
      </el-table>
    • data部分

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      data() {
      return {
      tableData: [
      {
      id: "1",
      date: "2016-05-02",
      name: "王小虎",
      address: "上海市普陀区金沙江路 1518 弄"
      },
      {
      id: "2",
      date: "2016-05-04",
      name: "王小虎",
      address: "上海市普陀区金沙江路 1517 弄"
      },
      {
      id: "3",
      date: "2016-05-01",
      name: "王小虎",
      address: "上海市普陀区金沙江路 1519 弄"
      },
      {
      id: "4",
      date: "2016-05-03",
      name: "王小虎",
      address: "上海市普陀区金沙江路 1516 弄"
      }
      ]
      };
      },
  • 配置拖动操作

    • 引入sorable

      1
      import Sortable from "sortablejs";
    • 初始化sorable,并配置拖动事件

      每次拖动的onEnd部分,通过index来splice来截取行,添加行,来更新data。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      mounted() {
      this.rowDrag();
      },
      methods: {
      rowDrag() {
      const tbody = document.querySelector(".el-table__body-wrapper tbody");
      const that = this;
      Sortable.create(tbody, {
      onEnd({ newIndex, oldIndex }) {
      const currentRow = that.tableData.splice(oldIndex, 1)[0];
      that.tableData.splice(newIndex, 0, currentRow);
      }
      });
      }
      }

注意事项

  • 如果没有设置row-key,拖动后会乱序
  • 建议可以设置两个tableData,tableData 和 tableDataCopy。table用于展示,每次拖动后修改tableDataCopy。这样不影响拖动的展示效果,也可以实现拖动的数据处理。再某些特殊表格拖动时,如果修改的是同一个tableDate,可能会出现一些异常。
  • 一个页面如果有多个表格,在拖动方法的时候需要注意,不建议有多个表格。

更多

  • sortableJS的更多配置见官网:http://www.sortablejs.com/options.html

  • 完整代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    <template>
    <div>
    <el-card>
    <el-table row-key="id" :data="tableData" style="width: 100%">
    <el-table-column prop="date" label="日期" width="180"></el-table-column>
    <el-table-column prop="name" label="姓名" width="180"></el-table-column>
    <el-table-column prop="address" label="地址"></el-table-column>
    </el-table>
    </el-card>
    <el-card>
    <pre>{{tableData}}</pre>
    </el-card>
    </div>
    </template>
    <script>
    import Sortable from "sortablejs";
    export default {
    data() {
    return {
    tableData: [
    {
    id: "1",
    date: "2016-05-02",
    name: "王小虎",
    address: "上海市普陀区金沙江路 1518 弄"
    },
    {
    id: "2",
    date: "2016-05-04",
    name: "王小虎",
    address: "上海市普陀区金沙江路 1517 弄"
    },
    {
    id: "3",
    date: "2016-05-01",
    name: "王小虎",
    address: "上海市普陀区金沙江路 1519 弄"
    },
    {
    id: "4",
    date: "2016-05-03",
    name: "王小虎",
    address: "上海市普陀区金沙江路 1516 弄"
    }
    ]
    };
    },
    mounted() {
    this.rowDrag();
    },
    methods: {
    rowDrag() {
    const tbody = document.querySelector(".el-table__body-wrapper tbody");
    const that = this;
    Sortable.create(tbody, {
    onEnd({ newIndex, oldIndex }) {
    const currentRow = that.tableData.splice(oldIndex, 1)[0];
    that.tableData.splice(newIndex, 0, currentRow);
    }
    });
    }
    }
    };
    </script>
    <style lang="less" scoped>
    </style>