如何实现表格的列拖拽的

因为使用el-table实现,所以一些抓取dom的class类通过el-table内置的类实现,实际如果是简单表格的话,可以自行增加class来实现 底层框架/原理 sortablejs 核心的拖拽原理,我们通过使用sortablejs提供的dom拖拽方案,实现 我们通过让sortablejs的el参数指定到el-table的header上 const query = ".el-table__header-wrapper thead tr" const el docuemnt.querySelector(query) // this.$el.querySelector(query) 那么表头的那一行的所有th就变为拖拽目标了,之后根据index的顺序变化,可以反推到列的切换上 核心代码 const sortable = new Sortable(el, { onEnd(evt) { let { newIndex, oldIndex, item } = evt; // 通知上级交换column位置 } }) 其他一些实现 跨表格实现 跨表格实现思路在于,通过在window上建立一个桥接用的map 缓存table的dom => vue实例对应关系 const sortable = new Sortable(el, { onEnd(evt) { const { to, from, pullMode } = evt; const toContext = window.bridge.get(to) const fromContext = window.bridge.get(from) let { newIndex, oldIndex, item } = evt; // 通知from和to对应的数据进行切换即可 } }) 拖拽优化 虽然核心代码很简单,但是不够完美,拖拽的时候只有表头可以进行拖动,实际上整列是没有跟着一起拖动的 所以我们需要进行样式上的优化,主要有两点 拖拽时候的影子 该列所有td跟随表头拖动 ...

December 11, 2021 · 5 min · 875 words · 水华

el-table拖拽开发实践

当前使用的 element-ui-el-table-draggable 提供了对element-ui内el-table的行进行拖拽排序的能力 不足之处 element-ui-el-table-draggable 只能配置两个参数,不支持列拖拽,不支持类似group等参数 改进和开发记录 基本属于重写了, 根据核心原理做了一个出来, 也就是,dom结构使用.el-table__body-wrapper tbody,然后直接交换el-table这个data对应index的数据 重点提示,需要给el-table增加row-key,保证交换之后重新渲染的数据正确!!! const elTableContext = this.$children[0] // 因为是通过slot引入 const container = elTableContext.$el.querySelector('.el-table__body-wrapper tbody') Sortable.create(container, { onEnd(evt) { let { newIndex, oldIndex, } = evt // 交换elTableContext.data里的位置,不展开了 exchange(oldIndex, newIndex) this.$emit('sort') } }) 之后我们解决几个核心问题 不能使用sortable.js的配置(例如group属性来多列表之间拖拽) 跨表格数据更新 支持列拖拽 expanded的row特殊处理 空处理 sortable.js配置 这个好解决,一方面是可以配置props, 另一方面,我们可以使用$attrs这个属性,将未在props内定义的属性直接获取 Sortable.create(container, { ...this.$attrs, // sortable的onXXX事件转为vue的事件格式emit掉 ...Object.keys(this.$listeners).reduce((events, key) => { const handler = this.$listeners[key] // 首字母大写 const eventName = `on${key.replace(/\b(\w)(\w*)/g, function($0, $1, $2) { return $1.toUpperCase() + $2.toLowerCase() })}` events[eventName] = (...args) => handler(...args) return events }, {}), onEnd(evt) { // 之前的处理代码 this.$emit('end', evt) }, }) 同时增加一个监听,自动更新对应的参数 ...

August 2, 2021 · 2 min · 295 words · 水华

el-table横向滚动条吸底处理方案思路

起因 工作中用到的 el-table显示大批量数据的时候,一页放不下,一般性的处理方案是限定了高,让表格固定表头之后内部可以滚动,不过因为实际操作中样式的问题,需要我把整个表格高度全部显示出来,这样就造成了一个问题,就是横向滚动不方便 不过作为mac用户已开始没啥感觉,但是被用windows的同事吐槽了好久,于是终于决定花半天时间解决 仓库 已开源,不想看的,可以直接看代码https://github.com/mizuka-wu/el-table-horizontal-scroll 或者安装npm i el-table-horizontal-scroll用指令的形式使用该项目 实现原理 其实是模拟了一个el-scroll进行同步,为了方便,制作成了一个指令 核心代码 通过Scroller类,创建一个scroller的dom,并插入到指令提供的el内部 el.appendChild(scroller.dom) 目标对象 const targetTableWrapperEl = el.querySelector('.el-table__body-wrapper') Scroller类 具体地址 主要负责了scroller的创建和管理,具体可以直接看代码 其模拟了一个el-scroll的dom结构(为了省的写样式) 大概会出现一个这样的dom结构 <!-- scroll/dom整个dom结构 --> <div class="el-scrollbar"> <!-- bar横条容器 --> <div class="'el-scrollbar__bar is-horizontal"> <!-- thumb滑块 --> <div class="el-scrollbar__thumb"></div> </div> </div> 然后整体就是对这个结构进行操作 例如,scroll的整体样式需要手动添加,让其可以自由浮动,然后显示在fixed列前,所以需要 scroller.style.height = '12px' scroller.style.position = 'fixed' scroller.style.bottom = 0 scroller.style.zIndex = 3 以及一些其他的调整,具体不再阐述 自动吸底原理 这个就是目前监听document的scroll事件,判断是否需要显示 核心判断代码就是判断el的底部是否出现在页面内 const viewHeight = window.innerHeight || document.documentElement.clientHeight const { bottom } = targetTableWrapperEl.getBoundingClientRect() // 当前的el-table的wrapper,可以在el内获取到 if (bottom <= viewHeight) { hideScroller() } else { showScroller() } 平时就position: fixed在页面底部,如果表格底部显示在页面里了,就自动隐藏即可 ...

July 9, 2019 · 2 min · 215 words · 水华