后管常见的树形组件的vue实现

本文主要展示一下4种树形组件基于 Vue2 和 Ant Design Vue 1.x 的一般的“实现效果”,和分析它们大致的“实现思路、经验”。【后文有图示】

前言——须知

在后台管理系统页面中,各类树形组件不可或缺,并且实现起来相对复杂。本文主要介绍其中几种最常见的

  • 树形图 多选选择框
  • 树形图 单选选择框
  • 查询展示功能 懒加载树形表格
  • 自定义 树形表格
  • (目录即本文页面左侧显示的目录导航)

本文主要展示一下它们树形组件基于 Vue 和 Ant Design Vue 的一般的“实现效果”,和分析它们大致的“实现思路、经验”。(也可以只看“实现效果”部分)


  • 根据个人经验,对于用于 选择/查询 的树形组件,若要确定他们的实现方案(或实现思路),一般要考虑以下几个方面的功能点:
    • 是否需要懒加载
    • 查询功能
    • 勾选回显:(带勾选框的,在初始化时或者查询条件下,可能需要回显勾选上“已选择”的)
    • 所有节点的“展开”控制
    • (如果是支持“多选”,还要考虑以下这些方面:)
    • 勾选联动
    • “全选”功能

对于各种“树”组件,都可以从以上几个方面入手考虑如何实现。 当这些功能需要叠加到同一个组件来实现的时候,组件复杂程度开始显著上升。

树形图 多选选择框

通常,“选择 业务系统 / 部门 这些类型的数据”的业务逻辑,可以用这种组件来实现。

这些类型的业务数据,如果一次性加载,可能总共有接近 1000 个节点,个人尝试过把这个量的数据直接放到 Ant Design Vue 的 a-select-tree 等组件里面,结果在首次弹出显示这样实现的组件和数据时太卡了;点击选择某个数据项的时候也会卡。官方又不予以优化。

小结,针对上述卡顿问题,可以自己二次开发封装实现组件来取而代之,并且实现了“懒加载”来优化。

其实还是用的 Ant Design Vue 的组件,只不过是基于它们做上层二次开发(并且自定义接管了部分Ant Design Vue组件的逻辑处理)。

multi-select-tree-outer-22090901

( 图1 ↑ )(图示只是仿造模拟图)

multi-select-tree-itself-22090501

( 图2 ↑ )(图示只是仿造模拟图)

“树形图 多选选择框”效果:

  1. 作为表单项显示“已选择的”业务系统或部门之类的。如图1
  2. 点击该表单项则弹出对话框。对话框带查询框查询功能,可多选。如图2
  3. 去除“已勾选项”弄得方便一点:可在对话框的上部区域操作。这样用户就不需要往下展开多层来找到目标节点

而下面这个效果要实现起来挺麻烦的:(查询状态判断、查询逻辑、展开逻辑、懒加载逻辑)

  • 当用户操作触发查询时,找到与查询匹配的节点,展开其所有祖先节点。(其他的节点暂时收起不展开,待用户逐个触发展开并懒加载。)
    • 另一种状态场景也要实现:非查询状态下,所有节点收起并且也是懒加载子节点。以获得比较流畅的性能和效果

“树形图 多选选择框”实现思路、经验:

在本文开头,已经给出比较全面的“常见功能点总结”。而到了实现具体某个组件,往往是基于“全面考虑”开始做“减法”:

【1】从以下几个角度考虑,节省实现很多不必要的功能实现和工作,以免工期拉得很长:

  • “已选择项”和“将选择项”的显示做分离: 令回显“已选择项”的复现逻辑没那么复杂了
    • (适用的情况是:需要回显的“已选择项”通常不多、选择某一节点时不需要带上选择它的那些祖先节点)
    • 效果是:“已选择项”只是做了简化处理,显示在对话框上方即可
    • 这样就不用为树形图,自行计算初始化组件时“勾选回显”的“已选择项”
  • 不必在树形图中实现“全选所有节点”的功能————因为在懒加载的场景下勾选“全选”有挺大的操作歧义

植入一条广告:一种比较全面地实现各个功能点的树形组件,见“隔壁文章” 一种常见的多层级树形表格组件

【2】而因为是懒加载场景,树形图计算“勾选联动”之类的,无法交给第三方组件 a-tree 组件那边计算,需要自行实现。

树形图 单选选择框

通常,“选择 业务系统 / 部门 / 菜单资源 / 组织 这些类型的数据”的业务逻辑,可以用这种组件来实现。

与上述“树形图 多选选择框”相同,该组件加载对应的业务数据同样可能有接近 1000 个节点,有些甚至总量能去到大几千。

所以同样地, “节点多导致卡顿,用懒加载解决” ,也是基于 Ant Design Vue 的组件,二次开发以实现。

single-select-tree-22090502

( 图3 ↑ )(图示只是仿造模拟了表面的样式:点击弹出该浮窗)

“树形图 单选选择框”效果:

说到这个组件要实现哪些功能:(可以说是上述“树形图 多选选择框”组件的功能子集)

  1. 作为表单项显示“已选择的”业务系统或部门之类的。如图3
  2. 点击该表单项则弹出浮窗。浮窗带查询框查询功能。如图3

而下面这个效果要实现起来挺麻烦的:(查询状态判断、查询逻辑、展开逻辑、懒加载逻辑)

  • 当用户操作触发查询时,找到与查询匹配的节点,展开其所有祖先节点。(其他的节点暂时收起不展开,待用户逐个触发展开并懒加载。)
    • 另一种状态场景也要实现:非查询状态下,所有节点收起并且也是懒加载子节点。以获得比较流畅的性能和效果

“单选选择框 树形图”因为不需要实现“多选”的功能,所以在实现层面是相对比较简单的。

查询展示功能 懒加载树形表格

通常在后台管理系统,查询展示的数据列表,要么就是“分页表格”的形式,要么就是本节所讲的这种“树形表格”的形式。

通常, 菜单资源 / 业务系统 / 部门 等等 很多种类型的数据的查询展示,只要是需要树状的,都可以用这种组件来实现:(如下面的 图4) (基于 Ant Design Vue 实现的组件)

lazy-tree-table-22090501

( 图4 ↑ )(图片源自网络,仅用作外观说明:树形表格)

  • 基本上都会优化为“懒加载”的形式:
    • 如果不是短周期的工程项目,那么数据量已经足够多了。
    • 要么分页,要么懒加载。通常二选其一。

“查询……树形表格”权衡实现“多选”

  • 假设在此基础上,还想要为表格实现“多选”功能,因为要兼顾其他交互的效果,开发成本一下子就上升了,建议预留更多的时间。
    • 实际情况是,在上面几种类型的业务数据当中,按实际情况只有个别的才需要做“多选”的功能
    • 相比于去实现“多选”,通常针对单个项的操作已经够用了。因为基本上每一个表格都会标配提供针对单个数据项的操作

“查询……树形表格”替换为组合式样式

另一种替代实现方式:拆分为组合式样式

如果表格要显示的数据的字段数量(也就是表格列数)不是很多的情况下,建议改造成这种:

  • 将控制“查询树”的功能抽取出来作为一个模块,放到页面左边的区域(这个树其实也是可以做懒加载优化的)
  • 结果就是一个“单选树形图+显示所选节点的子级列表”的组合,一左一右:(如下面的 图5)

lazy-tree-table-2-col-22090801

( 图5 ↑ )(图片源自网络,样式拼凑而成,仅用作外观说明)

  • “组合式”的缺点就是,需要占用更多的页面横向空间,所以表格列数如果多,就很难用
    • 针对这点可以优化,在合适的时机收起左树的占用空间转赠给右边表格区域
  • “组合式”优点就是,因为把树形的逻辑解耦了出去,所以当表格想要实现更多更复杂功能时的负担减轻了
    • 比如对比原来的“树形表格”,若需兼顾实现表格的“多选”功能,将少出现很多bug。
    • 比如对比原来的“树形表格”,若需兼顾实现表格的“分页”功能,将少出现很多bug。

自定义 树形表格

这种其实是向后台系统提交一组树状的数据。所以交互通常是“填写内容”或者“通过选择来录入内容”,然后把数据提交的。

特点:

  • 通常由于树数据的每一级数据类型不一样:下一级使用表格第二列、第三列来展示
    • (不同于 Ant Design Vue 的 a-table 内置提供的树形表格的“下一级数据显示为后续的表格行”)

custom-tree-table-22090902

( 图6 ↑ )(图片源自网络,样式拼凑而成,仅用作外观说明)

  • 实现方式并不唯一:
    • 可以直接利用 Ant Design Vue 的 a-table 合并单元格来实现表示父子级从属关系
    • 可以自己使用html拼接成这种表格,再优化样式
      • (自己使用html拼接实现的话,页面里面这些部件基本无法实现自动对齐,通常需要固定表格的某些列宽和行高)

常见实现场景:嵌套对话框内

这种“所提交的树形数据是表单数据的一部分的”对话框,对于它的可复用性不要抱有太高的期望。

“嵌套”往往是“树形图”的宿命。用于填写数据的树形组件可能也是一样的。因为它树形表格本身占据表单的空间就比较大,所以优先考虑将它设计为首屏收起来的,以“嵌套对话框内”的形式呈现。

  • 到这里做一个假设,假设这个对话框的数据,按要求要改造为一组表单数据的一部分。
    • 通常就是嵌套对话框的场景了。外层增设一个能填写的表单对话框
    • 此时在多数情况下,这个内层对话框组件的可复用性基本上变为零了。
      • (最大程度上只能做到复用这个组件内的某些模块,而不是复用这个对话框组件本身)

custom-tree-table-outter-22090801

( 图7 ↑ )(图片源自网络,样式拼凑而成,仅用作外观说明)

如图7,树形表格位于内层对话框。而外层对话框是一个数据表单,需要带上内层对话框(如刚才图6)里面的树形表格的数据一起提交。

这种嵌套对话框需求的隐藏要求:

这种嵌套对话框需求的隐藏要求:

  • 对于这种场景,内层对话框上的表单的数据,包括树形表格的数据最好是从上层对话框流入内层对话框组件
    • 因为,操作的用户有可能在这个内层对话框修改完数据之后,在这个内层对话框中点击“取消”。当用户再次打开内层对话框,内层对话框所要复现的数据,应当是需要照旧从上层对话框读取并且做格式化调整后传入内层的。
  • 即便不打开内层对话框,外层对话框也能直接带着内层对话框中的树形数据 走校验+格式化 然后提交。
    • 此时又存在着要求:外层对话框的校验规则和校验提示和内层对话框中的须看起来一致
    • 内外两层对话框的两组相似的 校验、校验提示和格式化逻辑,不能全都归属于内层对话框组件内

这种嵌套对话框可复用性: ≈ 0

  • 在实际业务场景中,由于外层对话框可能各不相同
    • 比如,外层对话框的数据格式主要由后端传过来的数据决定,需要优先考虑后端想要的格式,所以外接的外层对话框的数据格式和字段可能各不相同。
  • 又因为上面可以看到对话框之间内外关联太过紧密、是需要保持较多的一致性的
  • 间接导致了: 应对搭配各种不同的外层对话框,内层对话框组件的可复用性约等于零

还要兼顾原本繁琐的数据流和数据格式的处理,在嵌套对话框的场景下,变得更麻烦(在此略过没有细述),进一步打击了对话框组件的可复用性。

遇到这种情况,多申请一点工期慢慢做就可以了。

文章目录
  1. 前言——须知
  2. 树形图 多选选择框
    1. “树形图 多选选择框”效果:
    2. “树形图 多选选择框”实现思路、经验:
  3. 树形图 单选选择框
    1. “树形图 单选选择框”效果:
  4. 查询展示功能 懒加载树形表格
    1. “查询……树形表格”权衡实现“多选”
    2. “查询……树形表格”替换为组合式样式
  5. 自定义 树形表格
    1. 常见实现场景:嵌套对话框内
      1. 这种嵌套对话框需求的隐藏要求:
      2. 这种嵌套对话框可复用性: ≈ 0