给el-table加个补丁

1,291 阅读3分钟

一、背景

不知道各位有没有这种困扰,就是当遇到存在过多表格项的表格页时,每次想看右边更多内容,都得先滚动到底部,滚动el-table的滚动条,才能想看到的内容。就像这样

QQ录屏20240703211140 [MConverter.eu].webp

这样就有点啰嗦,我为了看一点点内容就得先用鼠标滚到底部然后拖动el-table的滚动条才能看到,于是产品就找到我喊我优化一下。

二、怎么弄?

1.二次封装el-table?

额,这个方案成本太高了,几百个页面每个页面都要这样弄,那我摸鱼时间不就没了。先解释下为什么会存在几百个页面呢,主要当初开发时我们用了ruoyi的低代码生成器生成的页面,没有对组件进行二次封装,所以就存在几百个页面的工程量。

2.写个全局方法对含有滚动条的el-table进行操作?

这个方法可行性不高,什么时候获取dom这是很大的问题。

3.Vue.extend?

Vue.extend是option api中的一个方法,官方对这个方法的解释是“使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。”,当时我看到这个方法时就想这个玩意是不是跟class的extends是一样的,可以继承父类的方法和属性,于是我写了个demo发现真的可以。

三、有哪些问题?

1.获取的dom是那个?

我们f12一下就发现这个容器属于一个类名叫“el-table__body-wrapper”的容器 image.png

并且当滚动条在左边时会多一个叫“is-scrolling-left”的类名 image.png

滚动条在右边时会多一个叫“is-scrolling-right”的类名 image.png

滚动条在中间时会多一个叫“is-scrolling-middle”的类名 image.png

这三个类名就是确定这个el-table存不存在横向滚动条。

2.怎么交互?

a.鼠标进入目标容器内,鼠标往左右移动,table就左右移动

显然这个交互不能通过,用户鼠标就左右动一下,你的table就左右移动就有点不符合常理,用户还以为是bug

b.鼠标进入目标容器内,鼠标左击并移动,table就左右移动

这个方案显然可以通过,但是这个交互在用户选择table上的文字时是同一个交互方式,所以说这两个场景我们要取舍,估计当时elementui团队在开发就想到了这点。经过我和产品的友好沟通,决定使用这个方案。

四、实现

1.新建一个js文件,编写以下代码作为我们基础的代码

import { Table } from 'element-ui'

const TablePatch = { extends: Table }

export default { install(Vue) { Vue.component(Table.name, TablePatch) }, }

component的名称一定要跟elmemtui中的名称对齐,要不然就是在新建了一个component

2.在mounted时我们获取下目标容器 image.png

3.判断下这个容器是不是含有横向滚动条的table

image.png

image.png

如果它是包含横向滚动条的table 我们就注册一系列事件 image.png 4.当鼠标在目标容器内点击时处理一下事件 image.png

我们需要记录下起始的位置,并且关闭用户选择table上的文字的方法,避免因左右拖动时误选到文字,进而产生出莫名奇妙的bug

5.当鼠标在目标容器内移动时处理一下事件 image.png

如果用户需要选择table上的文字需要先按下ctrl键才能选择

如果用户按下了ctrl键并鼠标移动那就是要选择table上的文字,我们就可以不用处理鼠标移动事件

我们记录下鼠标最终位置,并且算出移动了多少距离,把算出的距离赋值给目标容器的scrollLeft属性

image.png

6.当鼠标左击抬起或者鼠标离开目标区域我就就注销全部的事件

最终效果

QQ录屏20240703234200 [MConverter.eu].webp