1、引入依赖 sortablejs

npm install sortable.js --save

2、在mounted() 函数中分别引入两个自定义的方法 , 分别是行和列的拖动

Element UI 表格行拖动 element table列拖拽_vue


贴一下这两个方法,拖动行方法

dragSort() {
            let that = this;
            // 首先获取需要拖拽的dom节点
            const el1 = document.querySelectorAll('.el-table__body-wrapper')[0].querySelectorAll('table > tbody')[0];
            Sortable.create(el1, {
                disabled: false, // 是否开启拖拽
                ghostClass: 'sortable-ghost', //拖拽样式
                animation: 150, // 拖拽延时,效果更好看
                group: { // 是否开启跨表拖拽
                    pull: false,
                    put: false
                },
                onEnd: (e) => { // 这里主要进行数据的处理,拖拽实际并不会改变绑定数据的顺序,这里需要自己做数据的顺序更改
                }
            });
        }

拖动列方法

//列拖拽
        columnDrop() {
            const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
            this.sortable = Sortable.create(wrapperTr, {
                animation: 180,
                delay: 0,
                onEnd: evt => {
                    if(evt.oldIndex===evt.newIndex) return;
                    const oldItem = this.columnsConfig[evt.oldIndex];
                    const newItem = this.columnsConfig[evt.newIndex];
                    this.$set(this.columnsConfig,evt.newIndex,oldItem);
                    this.$set(this.columnsConfig,evt.oldIndex,newItem);
                }
            })
        },

2.1、这里值得注意一下就是拖动列这里卡了我很久,原因是因为表头数据是改变了,列表的数据也改变了,但是表头视图不更新原因是因为:在自定义表头的时候,由于是用的v-for循环生成的,因此会给每个循环体一个固定的key,导致数据频繁异步更新时,因为这个key没有变,所以el-table觉得表头数据是没有变化的,因此就只更新了整体表格数据、key值有变化的列的表头

导致出现了这种情况:正常

Element UI 表格行拖动 element table列拖拽_数据_02


有问题的:

Element UI 表格行拖动 element table列拖拽_拖拽_03


原因是我生成列的时候key绑定了固定值

Element UI 表格行拖动 element table列拖拽_vue_04


解决:

Element UI 表格行拖动 element table列拖拽_vue_05


建议key不要使用Math.random,因为这样会引起每次都会去刷新,从而造成资源的浪费,这里提供一个做法就是:key的值可以使用id,每当移动列的时候,监听回调函数(即下方columnDrop函数),就把两个列的key的值重新生成一个新的,这样就不会造成页面列表的抖动,列数据也进行改变了。

3、OK,问题解决。我的是弄成了组件,实现自定义表头,各位看官可以根据自己的需求弄,现在是贴全部代码:

Html

<template>
  <div class="TableDrag">
    <el-table
      :data="tableDatas"
      border
      @sort-change="sortMethods"
      :header-cell-style="{color: '#333333', fontSize: '16px', backgroundColor: '#F5F7FA'}"
    >
      <slot name="fixed"></slot>
      <el-table-column
        v-for="(item,index) in columnsConfig"
        :key="index+''+Math.random()"
        :sortable="item.sortAble"
        :label="item.filedZhName"
        :prop="item.filedEnName"
        :width="item.width"
        :column-key="index.toString()"
        :show-overflow-tooltip="true"
        align="center"
      >
        <template slot-scope="scope">
          <span
            v-if="item['filedDataType']=='text'||item['filedDataType']=='option'||item['filedDataType']=='mutiloption'"
          >{{scope.row[item.filedEnName]}}</span>
          <el-switch
            v-else-if="item['filedDataType']=='slots'"
            v-model="scope.row[item.filedEnName]"
            active-color="#4B7DF6"
            inactive-color="#C0C4CC"
            on-change="viewGoods(scope.row)"
          ></el-switch>
        <el-popover placement="right" trigger="click" v-if="item['filedDataType']=='zuocao'">
            <div class="items">离职</div>
            <div class="items">调动</div>
            <div class="items">删除</div>
            <div slot="reference" style="cursor: pointer;">...{{scope.row.undefined}}</div>
          </el-popover>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

JS

<script>
import Sortable from 'sortablejs';
export default {
    props:{
        columnsConfig:{ //表头
            type:Array,
            default:()=>{
                return [];
            }
        },
        tableDatas:{ //数据
            type:Array,
            default:()=>{
                return [];
            }
        }
    },
    data(){
        return{
        }
    },
    mounted(){
        this.dragSort();
        this.columnDrop();
    },
    methods:{
        //行拖拽
        dragSort() {
            let that = this;
            // 首先获取需要拖拽的dom节点
            const el1 = document.querySelectorAll('.el-table__body-wrapper')[0].querySelectorAll('table > tbody')[0];
            Sortable.create(el1, {
                disabled: false, // 是否开启拖拽
                ghostClass: 'sortable-ghost', //拖拽样式
                animation: 150, // 拖拽延时,效果更好看
                group: { // 是否开启跨表拖拽
                    pull: false,
                    put: false
                },
                onEnd: (e) => { // 这里主要进行数据的处理,拖拽实际并不会改变绑定数据的顺序,这里需要自己做数据的顺序更改
                }
            });
        },
         //列拖拽
        columnDrop() {
            const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
            this.sortable = Sortable.create(wrapperTr, {
                animation: 180,
                delay: 0,
                onEnd: evt => {
                    if(evt.oldIndex===evt.newIndex) return;
                    const oldItem = this.columnsConfig[evt.oldIndex];
                    const newItem = this.columnsConfig[evt.newIndex];
                    this.$set(this.columnsConfig,evt.newIndex,oldItem);
                    this.$set(this.columnsConfig,evt.oldIndex,newItem);
                }
            })
        },
        // 排序的方法
        sortMethods(type) {
        console.log(type);

        },
    }
};

data:

columnsConfig: [
                    {
                        filedEnName: "names",
                        filedDataType: "text",
                        filedZhName: "姓名",
                        closAble: false,
                        sortAble: true
                    },
                    {
                        filedDataType: "text",
                        filedEnName: "telphone",
                        filedZhName: "手机号码",
                        closAble: true,//是否可以关闭
                        sortAble: true,//是否可以排序
                    },
                    {
                        filedEnName: "zhanghao",
                        filedDataType: "text",
                        filedZhName: "账号",
                        closAble: true,
                        sortAble: false
                    },
                    {
                        filedEnName: "status",
                        filedDataType: "slots",
                        filedZhName: "账号状态",
                        closAble: true,
                        sortAble: false
                    },
                    {
                        filedEnName: "email",
                        filedDataType: "text",
                        filedZhName: "工作邮箱",
                        closAble: true,
                        sortAble: true
                    },
                    {
                        filedEnName: "ruzhiriqi",
                        filedDataType: "text",
                        filedZhName: "入职日期",
                        closAble: true,
                        sortAble: false
                    },
                    {
                        filedEnName: "zuocao",
                        filedDataType: "zuocao",
                        filedZhName: "操作",
                        closAble: true,
                        sortAble: false
                    }
                ],
                tableDatas:[
                    {
                        id:0,
                        names:"范德萨发大水",
                        telphone:"1245488",
                        zhanghao:"法大师傅",
                        status:true,
                        email:"223232",
                        ruzhiriqi:"2020-06-05"
                    },
                    {
                        id:1,
                        names:"范德萨发大水3333",
                        telphone:"1245488",
                        zhanghao:"法大师傅",
                        status:false,
                        email:"223232",
                        ruzhiriqi:"2020-06-05"
                    },
                    {
                        id:2,
                        names:"范德萨发大水111",
                        telphone:"1245488",
                        zhanghao:"法大师傅",
                        status:true,
                        email:"223232",
                        ruzhiriqi:"2020-06-05"
                    }
                ]

style:

.w-table {
    ::v-deep .el-table .darg_start {
       background-color: #f3f3f3;
      }
      .sortable-ghost {
        opacity: 0.4;
        background-color: #c1c1c1;
      }
      //表头高度
      ::v-deep .el-table th, .el-table tr{
        background-color: none;
        height: 56px;
      }
      //td字体和颜色大小
      ::v-deep .el-table{
        td{
          font-size: 14px;
          color: #666666;
        }
      }
 }