写了一个高可定制性的 Vue3 表格组件 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hc93
V2EX    Vue.js

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

  •  
  •   hc93 2022-06-16 22:01:35 +08:00 4027 次点击
    这是一个创建于 1221 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在做公司项目的 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 的各类元素的背景色,字体颜色,边框颜色等进行定制:

    截屏 2022-06-10 下午 6.20.55.png

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

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

    chrome-capture-2022-5-10 (5).gif

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

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

    23 条回复    2022-07-07 08:39:17 +08:00
    heliushao88
        1
    heliushao88  
       2022-06-17 05:03:15 +08:00 via Android
    厉害
    SniperXu
        2
    SniperXu  
       2022-06-17 09:38:47 +08:00
    牛逼,已给 star
    hc93
        3
    hc93  
    OP
       2022-06-17 10:19:22 +08:00
    @SniperXu 谢谢!
    akagishigeru
        4
    akagishigeru  
       2022-06-17 11:09:52 +08:00
    server-side 是指服务端 Json 模式渲染吗?这种模式对于自定义的事件该如何处理呢
    hc93
        5
    hc93  
    OP
       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
    linkopeneyes
        6
    linkopeneyes  
       2022-06-17 11:47:32 +08:00
    其实我不太喜欢用 slot 传参类型很难知道,可以给每列提供一个 render 更好推断类型,script 标签 lang 现在也支持 tsx 了
    cutchop
        7
    cutchop  
       2022-06-17 12:09:43 +08:00
    用 ag-grid 啊,大家都这么忙,你怎么有时间造轮子
    hc93
        8
    hc93  
    OP
       2022-06-17 12:15:48 +08:00
    @sjhhjx0122 是的 我看了 vuetify3 正在开发的代码也在用 tsx ,不排除之后 refactoring 的时候用 tsx
    hc93
        9
    hc93  
    OP
       2022-06-17 12:16:25 +08:00
    @cutchop 因为这个轮子算在了我工作的 task 里面了 带薪造轮子
    qrobot
        10
    qrobot  
       2022-06-17 13:09:25 +08:00
    @hc93 建议加上虚拟滚动,否则性能上存在很大的问题
    qrobot
        11
    qrobot  
       2022-06-17 13:12:43 +08:00
    @hc93 https://ui.lif.ink/components/data/table 我也在做表格,有兴趣可以交流, 不过我的实现方案和你的有点区别, 我是直接用 `div` 做的,没有用浏览器的 `table` 标签
    hc93
        12
    hc93  
    OP
       2022-06-17 16:59:20 +08:00
    @qrobot scroll load 的话很有必要加虚拟滚动,但是基于 pagination 的表格一般情况 row per page 也就设置成个 50,100 行,渲染 100 条 tr 元素并不会有多大的性能消耗。
    qrobot
        13
    qrobot  
       2022-06-17 17:19:30 +08:00
    @hc93 实际上业务场景里面需要在 tr 元素中做自定义渲染, 比如 添加一个图片,或则显示一个 svg

    10 × 100 = 1000

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

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

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

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

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


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

    你看看 10 列 100 行数据就已经有 1000 个元素了,还不包含其他表格头部的元素, 性能会下降的非常严重
    hc93
        19
    hc93  
    OP
       2022-06-17 20:43:24 +08:00
    @qrobot 有道理 加入 todo list 里面了,high priority,多谢老铁提醒。
    hc93
        20
    hc93  
    OP
       2022-06-17 20:51:15 +08:00
    @qrobot 你 demo 有没有发错
    hc93
        21
    hc93  
    OP
       2022-06-17 21:00:38 +08:00
    @qrobot 是下拉款的 demo ,sorry ,没看清楚。
    alleluya
        22
    alleluya  
       2022-07-06 10:01:12 +08:00
    @qrobot
    @hc93
    想请教下两位 table 这种组件 如果在移动端要用 有什么比较好的现成的吗? 或者你们在开发现有的这个 table 组件中 有考虑在移动端上使用的场景吗?
    qrobot
        23
    qrobot  
       2022-07-07 08:39:17 +08:00
    @alleluya 虽然没考虑,但是理论上是兼容移动端的,你可以试试,随时可以反馈
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2734 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 14:13 PVG 22:13LAX 07:13 JFK 10:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86