Element-ui el-table 使用 SortableJS 实现表格拖拽排序,字段主键和非主键不可相互拖拽,后端自动生成的数据不可拖拽

2,275 阅读2分钟

前言

Element-ui el-table中只有表头的字段排序,并没有拖拽排序。如果需要实现拖拽排序,可以采用SortableJs来实现拖拽排序。

项目需求
  1. 点击字段排序按钮后进行拖拽排序,第一列由原来的选择框,变为拖拽图标。
  2. 没点击字段排序按钮,不可进行拖拽操作。
  3. 选择框,序号,字段名添加fixed:left,使其固定在左侧。
  4. 系统自动生成的字段不可拖拽。
  5. 主键不能和非主键相互拖拽,只能主键和主键相互拖,非主键和非主键相互拖。
  6. 拖拽结束后,点击保持按钮将整个表格变化后的数据都重新传给后端。

第一步 安装sortablejs

npm install sortablejs --save

第二步 在需要实现表格拖拽的.vue文件中引入

import Sortable from 'sortablejs'
示例:
  • 主键不能和非主键相互拖拽 主键和非主键不能相互拖拽.gif
  • 非主键和非主键相互拖拽 非主键和非主键相互拖拽.gif
  • 系统自动生成的字段不可拖拽 系统自动生成的字段不可拖拽.gif
  • 取消或者保持后不可进行拖拽操作 不可进行拖拽操作.gif
<template>
    <el-table
        empty-text=" " 
        ref="dragTable" 
        row-key="id" 
        v-loading="table_loading" 
        :header-cell-style="{ background: '#F2F6FA', color: '#2C3D55', }" 
        :data="tableData" 
        style="width: 100%" 
        class="USN" border 
        :height="tableHeight" 
        @selection-change="handleSelectionChange" 
        :row-class-name="rowClassName" > 
         <el-table-column type="selection" align="center" width="40" v-if="!sortValue" > </el-table-column> 
         <el-table-column fixed width="50" v-else align="center"> 
             <template> 
                  <img src="@img/sort.svg" style="width: 12px; height: 12px; padding-right: 4px" />
             </template>
         </el-table-column> 
         <el-table-column fixed="left" width="60" label="序号" prop="id">
         <template slot-scope="{ row }"> 
             <span>{{ row.$index }}</span> </template> 
         </el-table-column>
         ...
     </el-table>
 </template>
// 开启排序 
enableSorting(){ 
    this.fieldOrder = true; // 来控制按钮变取消和保持 
    this.$refs.smTableList.enableSorting(); //调用子组件的方法 
},   
// 开启排序 
enableSorting() { 
    this.sortValue = true; 
    this.disabled = false; 
    this.setSort(); 
},
//给每行data.row.initFlag === 1 添加class名字 
// initFlag === 1 为系统生成不可拖拽 
rowClassName(data) { 
    if (data.row.initFlag === 1) { 
        return "rowClassFilter"; 
    } 
},
setSort() { 
    const tableTag = this.$refs.dragTable.$el;
    // 字段设置fixed="left"是,绑定一层的话会出现设置fixed的字段无法拖拽 
    const fixedBodyWrapper = tableTag.querySelector( ".el-table__fixed-body-wrapper table tbody" );  // 绑定fixed这一层的表格
    const bodyWrapper = tableTag.querySelector( ".el-table__body-wrapper tbody" );  
    if (fixedBodyWrapper) { 
        this.sortable = Sortable.create(fixedBodyWrapper, { 
        filter: ".rowClassFilter", 
        onEnd: this.onSortEnd, 
        //如果className === rowClassFilter 系统自动生成的不可以拖拽 
        onMove({ related }) { 
            return related.className.indexOf("rowClassFilter") === -1; 
        }, 
        sort: this.sortValue, 
        disabled: this.disabled, 
    }); 
} 
    if (bodyWrapper) { 
    this.sortable = Sortable.create(bodyWrapper, { filter: ".rowClassFilter", 
    onEnd: this.onSortEnd, 
    onMove({ related }) { 
        return related.className.indexOf("rowClassFilter") === -1; 
    }, 
    sort: this.sortValue, 
    disabled: this.disabled, 
    }); 
   } 
  }, 
onSortEnd(evt) { 
    const { oldIndex, newIndex } = evt; 
    const movedItem = this.tableData[oldIndex]; 
    const targetItem = this.tableData.length > newIndex ? this.tableData[newIndex] : null; //判断是不是主键 
    if ( movedItem.primaryKeyFlag !== (targetItem ? targetItem.primaryKeyFlag : false) ) { 
        this.$message.error("主键和非主键不能相互拖拽"); 
        this.sortable.captureAnimationState(); // 捕获当前动画状态 // 使用DOM操作将项目放回原来的位置 
        evt.to.removeChild(evt.item); 
        evt.from.insertBefore(evt.item, 
        evt.from.children[evt.oldIndex]); 
        this.sortable.animateAll(); // 应用动画使元素返回原位 return; 
      } 
      //数据交换位置
    this.tableData.splice(newIndex, 0, this.tableData.splice(oldIndex, 1)[0]); 
},
// 拖拽时,选择框的表头隐藏掉
<style> 
.dim .el-table__fixed-header-wrapper .el-table__header th:first-child div { 
    display: none !important; 
 }
</style>

总结

第一次在这里写笔记,希望对大家有用。工作顺利,工作稳定。

欢迎一键三连哦~

各位,加油!!!