vue树形组件_根据公司的业务需求我是这样封装组件的

作者:lin1997
原文链接:https://juejin.im/post/6888125003024629768

前言

一个项目下来发现有很多看似相似但又有区别的功能,想想如果一个一个的去写这种相似又有区别的功能,就会显的乏味枯燥,而且更关键的是这样的代码使得项目更难的去维护。如何让项目焕然一新,并且方便以后需求迭代的时候更好的维护呢?那就动手封装组件吧,让那些相似的功能需求都统一管理统一配置。

需求

当我拿到需求的时候,我先看了element-ui的组件是否满足我业务上的需求(ps:如果在 elemnt-ui 组件的基础上去做改造也是 ok 的),但后来我发现 element-ui 的表格组件无法满足我这次的业务需求,通过改造element-ui当中的组件也超级麻烦。最后,我还是决定自己封装一个多功能的 table 组件吧.......功能需求如下:1.表格数据的树形渲染并且同个父级下的同层级可拖拽,不同层级无法完成拖拽。2.表格行可操作(ps:比如编辑,删除,查看详情)3.表格的顶部可操作(ps:展开,排序)4.表格尾部可分页 5.表格可多选(ps:表格带复选框)

多功能的表格组件

安装插件

npm install element-ui sortablejs -S

在项目中我是使用sortablejs实现拖拽的,以及使用elemnt-ui的分页组件实现分页的功能。

树形结构数据如何渲染

因为是树形结构的数据,所以我想到了递归组件。在设计递归组件之前先了解树形结构的数据是长什么样的。59efad95cb61123177e78b9bc11ff7b3.png如下图通过给组件命名 recursiveRow,并且在该组件的模板里使用该组件。好吧,到这里即完成了递归组件的第一步...da817efdf429e9f375347836b3af600f.png我将每一行设计成一个组件,如果该行数据有 children 那么就在渲染一次 recursiveRow 组件。好吧,到这里实现了递归的条件了。接下来就是完成每一行数据的代码编写了。具体如何完成每一行数据的代码编写我等后续再补充,接下来我们先来了接这个组件的配置表。

表头的配置项设计

这个组件通过表头的配置实现了组件的统一管理,表头配置项的设计主要是通过一个JSON来实现的。JSON是通过字段namepropsbeforeimagesactionsattrselecttreenameprops

基础配置

表格的基础配置是通过字段nameprops来设计的。fdf80fadb48ecce31ed3b34788b61d7f.png这样的基础配置渲染出来页面如下:a1f30c3c67f4e1eb93a37907576476a1.png

其他配置

一般一个表格组件不仅仅只有渲染的功能就完事了,还会有其他的操作,比如删除,编辑,比如复选框,以及属性数据的样式配置等等...行操作的表头配置我是通过actions配置进行的,可以传递点击的事件,并且执行该事件可以获取每行的数据,以及改行的索引,还有事件对象。其属性是通过attr来配置的。

f466d8b797594abca8869a4ea4fabb19.png

如果需要复选框可通过配置select,将改字段设置为true。通过配置attr来配置属性,当然如果不传也可以,有默认值。那如何获取到每行勾选所对应的值呢?留个疑问,后续我们再讲述。

c60c2dc696784cdf96e621964b02a187.png

如果确定了哪个字段是需要渲染成树形的图案,可以通过配置tree,将改字段设置为true就可以,可以通过配置before可以特殊渲染每一个格子的数据。

9420c0662008e27f957582240907a394.png

当完成表头配置项的设计之后,如何传递属性,如何设计上面讲到的每行编码就是接下来要考虑的。这里的核心是通过 v-bind,当 v-bind 不带参数的是将会把整个对象的所有属性都绑定到当前元素上。以及v-on将事件一一绑定到元素上。组件中使用了 \$attrs[1]对象属性的集合和\$listeners[2]对象事件的集合来实现属性的跨阶级传递,监听事件的传递。将绑定在 table 组件的属性和事件通过跨阶级传递给递归组件,使得递归组件接收属性和事件。自定义递归组件:

7874f3c76fe360c8c10c25324df641dd.png

有了表头和表格数据就可以实现每行的编码了,就是遍历 table 数据和表头数据.,来完成每行的编码,并将其属性进行绑定。在实现每行的过程中,使用了 vue 提供的一个动态组件component来实现动态的标签渲染。

功能集合

功能解析说明

  • 在实现业务需求功能的过程当中,因为我设计的是递归组件,所以每一个递归组件都是一个作用域。大部分人都会在递归当中混淆,它们只不过是层层嵌套的作用域,但它们又是独立的个体。(ps:在这里我也踩过坑)

  • 刚刚上面提到的如何获取每次勾选的值。是通过给 table 绑定select-change事件,该事件会返回每次所勾选的值。其实现的思想就是保存每次勾选的值,过滤每次反选的值,具体的想了解实现过程可查看源码。

  • 讲到表格的顶部,那我就把尾部一起讲了吧。在布局上顶部和尾部是通过具名插槽slot来实现的。所以可自定义顶部的操作以及尾部的分页。

  • 表格可展开是通过表格内部暴露出来一个函数openAllTree来实现的,可以通过绑定ref再外部获取这个函数。openAllTree其实现的思想是通过改变数据,让数据去驱动视图;在递归组件中封装一个函数用来将当前作用域的内部属性更新,在 table 组件中循环执行每一个递归组件的函数。具体的想了解实现过程可查看源码。

  • 表格可排序是通过绑定属性isSort来开启和关闭排序功能。给每一个递归组件绑定一个ref属性,那么通过 new Sortable 实例实现同层级的拖拽(这里的同层级就是相同层级节点并且同个父节点的可互拖)。其实现的思想是通过绑定ref属性可获取当前组件的数据流(ps:因为每一个组件都有自己的作用域,所以是独立的),那么通过数据再去驱动视图。在这里还要注意isSort的数据更改以及拖拽完成之后的表格数据更新,所以在通过接收属性 callback 来实现表格数据的更新(ps:回调函数的思想)。内部是通过函数handlerSort实现的,具体的想了解可查看源码。

  • 最后在完成公司的业务需求之后,我又自己写了一个当点击编辑之后可直接在表格上修改数据的功能。主要是 table 组件暴露出的一个内部函数handlerEdit。其思路是通过增加改行的字段component来配置修改HTML标签,以及修改行的该字段的数据。具体的实现可查看源码。

  • 优化了表格的 loading

使用 table

自定义组件 table

2c8e1b2cd97672201f6b56f84f1614e4.png

如下图:

93f62d8cf90dc4b4a27d17dfacdeeae8.png

样式可自行修改哈~~

源代码

组件源码地址可查看:源码地址[3]

总结

很多人可能会觉得那么多组件库为什么要自己封装组件呢,有这个必要吗?其实在分析这个需求的时候,我也曾尝试去找资源,但发现基本上都是文件夹一样的拖拽功能...所以,我后来就决定自行封装。当然在开发的过程当中,我觉得封装组件是有必要的,既不会代码冗余显得臃肿而且还实现统一配置管理可以让项目更稳步的实现迭代。最后,对各大掘友有帮助的话希望赏个 star ~(ps:不要吝啬哦)

参考资料

[1]

$attrs: https://cn.vuejs.org/v2/api/#vm-attrs

[2]

$listeners: https://cn.vuejs.org/v2/api/#vm-listeners

[3]

源码地址: https://github.com/hhl-web/vue-ts-components

交流讨论

欢迎关注公众号「前端试炼」,公众号平时会分享一些实用或者有意思的东西,发现代码之美。专注深度和最佳实践,希望打造一个高质量的公众号。

173a93bc1d071da6e2fe05ab02bc3dcc.png

公众号后台回复「加群」,拉你进交流面试群。

如果你不想加群,只是想加我也是可以的。

如果觉得这篇文章还不错,来个【分享、点赞、在看】三连吧,让更多的人也看到~

45ff76819346b0317a769ce587652a91.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值