写了一个高可定制性的 Vue3 表格组件

2022-06-16 22:01:35 +08:00
 hc93

最近在做公司项目的 vue2 到 vue3 的迁移,vue2 的项目一直使用的 Vuetify 这个 UI 框架,用的最多的就是 Vuetify 的 data table 组件,client 模式和server-side 模式都在用,但是 Vuetify3 的进度有些慢,等了很长时间目前还处于 beta 版本,所以就借鉴 Vuetify2 的 data table 组件的 UI 和 API ,自己写了vue3-easy-data-table这个 data table 组件。项目地址在这里: https://github.com/HC200ok/vue3-easy-data-table

其实市场上已经有很多成熟的 Vue3 的组件库了,比如 naiveui ,element next 之类的,这次自己造轮子主要是想尝试用 vite+ts+vue3 这一套开发和发布一个组件。公司内部有啥比较偏的需求的话,实现起来也比较方便。

我个人觉得vue3-easy-data-table有个特点就是它的高度可定制性,非常适合前端进行二次封装。

比方说,基于 Vue.js 的插槽功能,你可以像下面的例子一样定制表格的某一栏和 loading 效果:

<EasyDataTable :headers="headers" :items="items">
    <template #team="{ teamName, teamUrl }">
        <a :href="teamUrl">{{ teamName }}</a>
    </template>
</EasyDataTable>

定制栏:

<EasyDataTable :headers="headers" :items="items">
    <template #loading>
      <img src="https://i.pinimg.com/originals/94/fd/2b/94fd2bf50097ade743220761f41693d5.gif" style="width: 100px;height: 80px;"/>
    </template>
</EasyDataTable>

定制 loading 效果:

另外,使用vue3-easy-data-table提供的颜色相关的属性,可以对 table 的各类元素的背景色,字体颜色,边框颜色等进行定制:

data table 这种组件其实还算蛮复杂的,集成了很多功能,比如搜索啊,排序啊,筛选啊等等,有的人只用功能 A ,有的人只用功能 B ,所以我开发的时候尽量保留了 js 的核心逻辑,而一些搜索框啊,筛选 menu 之类的元素的我就没有在组件内部实现,我暴露了相关的变量和方法,前端开发人员可以基于这些定制自己的搜索框等相关 UI 。一来尽量减小组件的 size ,二来从结果上来看,也算高可定制性的一种体现吧(其实是我比较懒,给我 star⭐我就加😂)

比方说,vue3-easy-data-table暴露了一些与 table footer 相关的变量和方法,利用这些变量和方法,你可以在vue3-easy-data-table的外部定制自己的 footer 来实现导航等功能:

今后也会基于 Vue.js 的插槽功能实现表头的一些定制功能。

最后贴上在线文档: https://hc200ok.github.io/vue3-easy-data-table-doc/ 欢迎使用,有建议或其他功能需求的老铁也欢迎提 issue 。

3491 次点击
所在节点    Vue.js
23 条回复
heliushao88
2022-06-17 05:03:15 +08:00
厉害
SniperXu
2022-06-17 09:38:47 +08:00
牛逼,已给 star
hc93
2022-06-17 10:19:22 +08:00
@SniperXu 谢谢!
JaguarJack
2022-06-17 11:09:52 +08:00
server-side 是指服务端 Json 模式渲染吗?这种模式对于自定义的事件该如何处理呢
hc93
2022-06-17 11:41:04 +08:00
@JaguarJack server-side 模式是指,每次跳转到新页面都要通过 restful api 或者服务端渲染来获得新页面的经过排序,分页,搜索过的数据。这里是相关文档和 demo: https://hc200ok.github.io/vue3-easy-data-table-doc/features/server-side-paginate-and-sort.html
sjhhjx0122
2022-06-17 11:47:32 +08:00
其实我不太喜欢用 slot 传参类型很难知道,可以给每列提供一个 render 更好推断类型,script 标签 lang 现在也支持 tsx 了
cutchop
2022-06-17 12:09:43 +08:00
用 ag-grid 啊,大家都这么忙,你怎么有时间造轮子
hc93
2022-06-17 12:15:48 +08:00
@sjhhjx0122 是的 我看了 vuetify3 正在开发的代码也在用 tsx ,不排除之后 refactoring 的时候用 tsx
hc93
2022-06-17 12:16:25 +08:00
@cutchop 因为这个轮子算在了我工作的 task 里面了 带薪造轮子😂
qrobot
2022-06-17 13:09:25 +08:00
@hc93 建议加上虚拟滚动,否则性能上存在很大的问题
qrobot
2022-06-17 13:12:43 +08:00
@hc93 https://ui.lif.ink/components/data/table 我也在做表格,有兴趣可以交流, 不过我的实现方案和你的有点区别, 我是直接用 `div` 做的,没有用浏览器的 `table` 标签
hc93
2022-06-17 16:59:20 +08:00
@qrobot scroll load 的话很有必要加虚拟滚动,但是基于 pagination 的表格一般情况 row per page 也就设置成个 50,100 行,渲染 100 条 tr 元素并不会有多大的性能消耗。
qrobot
2022-06-17 17:19:30 +08:00
@hc93 实际上业务场景里面需要在 tr 元素中做自定义渲染, 比如 添加一个图片,或则显示一个 svg

10 × 100 = 1000

每次在渲染拦截的时候多添加一个逻辑呢么就是 10 × 1000 × N 个 元素, 你想想这是多么恐怖的一个数据量

因为你现在演示的 demo 里面没有做复杂的渲染拦截,所以觉得性能还可以, 我用 antd 原生的表格, 在实际业务中使用,超过 50 条数据,就很卡顿了。当然卡顿的原因就是因为自定义单元格渲染导致的, 你可以做一下测试。

在 antd 中如果没有负责的渲染逻辑当然是没问题的,但是如果加上了,很难不卡顿
qrobot
2022-06-17 17:20:56 +08:00
@hc93 举个很简单的例子, 如果显示 100 条数据没有滚动条,那么就会占据很大的布局空间, 这实际上是不符合用户使用习惯。 例如显示 20 列的时候。 那个时候必须要有滚动条。否则很难看
hc93
2022-06-17 17:21:21 +08:00
@qrobot 不过考虑到也有可能 row per page 设置成很大的 case 今后会考虑加入虚拟滚动
qrobot
2022-06-17 17:23:18 +08:00
@hc93 你可以稍微把列的数量调大到 20 列, 行数量调整到 100 行,你再试试性能。

一个表格的就占据了 20×100 个元素。

如果页面这种表格达到了 3,4 个会怎么样? 那么就是 3 × 20 × 100 = 6000 个元素,你想想这是多么恐怖的一个性能消耗!
qrobot
2022-06-17 17:25:27 +08:00
@hc93 如果你打算把这个表格做好,虚拟滚动肯定是必须要做的, 否则性能上很难扛住,并且虚拟滚动越早做,后面的代码改动就越少,否则一改就是大概,后面只能和 antd 一样做一个 layout 拦截让用户自己去实现虚拟滚动,到时候就会丢失`展开行`, 固定列, 合并单元格等等逻辑
qrobot
2022-06-17 17:30:53 +08:00
@hc93 你看这个例子,只是简单的下拉框,在 1000 条数据上的表现


https://codesandbox.io/s/solitary-voice-m3vme?from-embed

你看看 10 列 100 行数据就已经有 1000 个元素了,还不包含其他表格头部的元素, 性能会下降的非常严重
hc93
2022-06-17 20:43:24 +08:00
@qrobot 有道理 加入 todo list 里面了,high priority,多谢老铁提醒。
hc93
2022-06-17 20:51:15 +08:00
@qrobot 你 demo 有没有发错

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/860143

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX