V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hc93
V2EX  ›  Vue.js

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

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

    最近在做公司项目的 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 谢谢!
    JaguarJack
        4
    JaguarJack  
       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
    sjhhjx0122
        6
    sjhhjx0122  
       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   ·   实用小工具   ·   1027 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 22:22 · PVG 06:22 · LAX 14:22 · JFK 17:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.