哈喽,大家好又是我。昨天有集体在群里问:“基于 elementUI 如何实现拖动批改列宽度,并同步在多个表格中”

这个性能其实听常见的,在不同的使用者眼中关注点就应该是不一样的。比方:

  • 我的项目的主管,更关怀进度
  • 前端开发,关怀设计稿、接口什么时候提供
  • 后端开发,关怀前端什么时候写完,什么时候联调
  • 测试人员,关怀什么时候提测,以及对应人员是谁

咱们的目标是:针对于不同的人群,显示不同的字段,不同的排序规定(index、fixed)。那好,咱们先来剖析一下实现这样的性能都须要做什么。

后期调研

elementUI 反对那些性能、回调?

  1. 宽度管制

    1. 宽度是否能够通过参数管制? 提供,给 el-table-column 组件增加 width 属性即可。
    2. 参数是首次无效,还是动静更新?动静更新所以能够应用 :width
    3. 是否提供了拖拽调整宽度的计划?增加 border ,并且开启 resizable (默认开启)。

      1. 是否提供了回调函数?header-dragend(newWidth, oldWidth, column, event) 当拖动表头扭转了列的宽度的时候会触发该事件
      2. 是否提供了API用于获取以后宽度配置?没有提供
  2. 字段程序

    1. 程序是否能够通过参数管制?没提供,看了一遍并且搜寻 排序、程序、index 等关键词并无播种。次要排序能力都是对内容区域。
    2. 如果无奈通过参数配置,那么通过什么中央能够影响到排序规定?咱们能够通过批改 <el-table-column> 的程序来管制。

剖析

通过调研 elementUI 发现能够近乎实现这项工作,那么咱们就不思考其余计划了。只把获取以后宽度配置这一个问题解决就好了。

思考一下,怎么改宽度?这不就 style="width: 10px" 行内款式嘛,这也太简略了。

关上控制台一看,粗率了,干干净净什么都没有。这就离谱了,魔法吗?哈哈,当然不是,咱们能够看到有个 colgroupcol 标签,专门用来管制列宽。

那就简略了,咱们间接获取即可。

实现代码

宽度管制(自带)

重点是加 border

<el-table :data="tableData" border @header-dragend="headerdragend" style="width: 100%">    <el-table-column v-for="column in tableTitleList" :fixed="column.fixed" :prop="column.prop"        v-if="column.isShow"        :label="column.label" :width="column.width">    </el-table-column>    <el-table-column fixed="right" label="操作" width="100">        <template slot-scope="scope">            <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>            <el-button type="text" size="small">编辑</el-button>        </template>    </el-table-column></el-table>

操作之后获取宽度 @header-dragend

通过 @header-dragend 拿到告诉,而后去获取节点上的实在数据

headerdragend(newWidth, oldWidth, column, e) {    // 获取到触发节点,也就是你拖动的是哪一个    var el = e.target;        // 获取到以后 table 的 colgroup col 节点,用于前面获取宽度    // getParentNodes 是一个模拟 $(el).parents() 的办法    var colList = getParentNodes(el, 'table').querySelectorAll('colgroup col');        // 获取以后拖动的是第几个,不便后续检测 DOM 是否已更新    var currentColIndex = this.tableTitleList.findIndex(item=>item.label == column.label);    if(currentColIndex == -1){        return console.warn('找不到拖动列')    }        // 批改配置列表,把当前列设置为固定宽度    this.tableTitleList[currentColIndex].widthEnable = true;    // 起了一个定时工作去获取最终的宽度    clearInterval(headerDragendInterval)    headerDragendInterval = setInterval(()=>{        // 判断一下指标列的宽度是否为最终宽度        if(colList[currentColIndex].width == newWidth){            this.changeColumnWidth(colList);            clearInterval(headerDragendInterval)        }else if(colList[currentColIndex].width == oldWidth){            console.info('须要期待渲染')        }else{            console.warn('异样值');            this.changeColumnWidth(colList);            clearInterval(headerDragendInterval)        }    }, 10)}

管制程序

因为数组是有程序的嘛,所以应用 v-for 来循环,而后扭转数组中的程序,就能够扭转渲染进去的内容程序

<el-table :data="tableData" border @header-dragend="headerdragend" style="width: 100%">    <el-table-column v-for="column in tableTitleList" :fixed="column.fixed" :prop="column.prop"        v-if="column.isShow"        :label="column.label" :width="column.width">    </el-table-column>    <el-table-column fixed="right" label="操作" width="100">        <template slot-scope="scope">            <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>            <el-button type="text" size="small">编辑</el-button>        </template>    </el-table-column></el-table>

拖动排序

这块我间接应用 Sortable 来实现性能,正好也是群里一个人问的。在 onEnd 的时候把操作同步到数据源就OK了

initSort(){    var el =  document.querySelector('#sortWrap')    var that = this;    Sortable.create(el, {        delay: 100,        sort: !0,        forceFallback: !0,        scrollSensitivity: 100,        animation: 150,        ghostClass: "gift-ghost-item",        chosenClass: "gift-chosen-item",        onEnd: function(t) {            that.tableTitleList.splice(                t.newIndex,                 0,                 that.tableTitleList.splice(t.oldIndex, 1)[0]            )        }    })},