引言:在程序员眼中,文件夹只不过是带有命名空间的‘数据项集合‘而已。
本文以假设开篇,希望你可以带着思考参与本次分享,全程支持随时打断和提出不同的声音。
假设:如果让你来设计一个文件夹系统,你会怎么做?
-
总结一下:
-
文件夹也是一个列表里的一个数据源;
-
文件夹数据源需要自己的视图渲染;
-
需要丰富交互;
- 拖拽
- 拖入效果
- 右键新建
-
配套组件开发;
- 面包屑组件
- 搜索组件
-
随时拔插:文件夹模式想要和不想要只在一念之间。
- 资源一定是以路径或者命名空间来存放的
-
所以一个完整的文件夹封装设计包含:
- 数据源处理
- 渲染封装
- 组件联动
- 解耦
剖析文件夹模式之 -- 数据源设计
我们的文件夹设计都是站在数据集合(Array)的基础上进行构思,而数组的展现形式通常由数组结构来决定,我们在这里粗略的分为两种类型:
-
平铺
-
表格
-
通过列(column)来渲染
- function render(value, record) { return ... }
-
-
卡片
-
通过预设的View视图来渲染
- <CustomCardView />
-
-
-
非平铺
-
Tree
- 本身可以展示多结构数据,其实就是前端的『文件夹模式』。
-
从这里我们可以看出,在数据源上我们要去解决:
-
平铺数据的非平铺展示,也就是一层层展示平铺数据;
- 我们通过 路径 来表示资源层级,可以在数据处理阶段清楚知道属于当前层级的数据源,我们把路径存放在相对全局的地方,去对他的修改进行监听;
- 当 路径 变动,意味着层级调整,资源同时也要更新。
-
数据源到最后都会走到渲染层,我们要标识属于文件夹的数据源,以便于渲染层知道谁是文件夹。
- 在原有的数据源基础上会插入文件夹的数据源,并写入特殊标识(我们用isFolder)
剖析文件夹模式之 -- 渲染封装
当组件接收到数据源,我们在渲染层可以根据不同的数据源渲染不同的视图,在这里我们就可以区分文件夹样式和非文件夹样式,区分规则就是我们上面标识的: isFolder.
当前渲染层需要包含的功能:
- 可以自定义触发方式: 单击 双击 悬浮停留 等等
- 触发回调:去修改 path
到这里就会走上两个岔路:
- 业务层碰到 isFolder 就去渲染一个文件夹样式, 多个业务层要写多个文件夹样式
- 在更为通用的地方去检查数据源,如果有isFolder,就提供一个默认的文件夹渲染方式,同时提供一个口子可以让你在业务层传入一个渲染,并且通用的处理好所需要的功能。
我们的做法是后者。
剖析文件夹模式之 -- 组件联动
文件夹的交互比较丰富,常见的交互包含但不局限于:拖拽,批量拖拽
所以我们需要有配套的组件支持以下功能:
- 可拖拽组件 -- 支持自定义渲染拖拽视图,包含拖拽的生命周期(start, end等等)
- 拖拽目标组件 -- 当拖拽到目标组件会有鼠标或者样式变动,包含拖拽进入、离开和放入等等的生命周期
- 右键点击新建组件 -- 全局包裹Table
- 面包屑文件路径导航
- 搜索
同样的岔路,理应同样的选择:
我们在更为通用的层级上嵌入了上面较为通用的组件,使得当前的Table只需要传入tableOptions和回调函数,就可以完成功能的使用。
如何工作?
数据源处理完毕后,我们主要是通过各个回调函数拿到当前有关于文件夹的所有动作。
由回调函数和回调函数的参数来告知,我们需要 修改数据源 还是 修改路径->重新请求数据源
如何拔插该文件夹功能?
-
在交互层:
- 当我们不需要文件夹的非平铺展示的时候,在外层我们通过类似 enableFolder 的参数来使通用层的文件夹处理关闭,请求参数也不会再自动拼接路径。
-
在数据源层:
- 同时,你的数据源应该无需请求文件夹列表,enableFolder 仅仅关闭的是有关于文件夹的交互。
文件夹模式的设计基于后端的结构支持。