去年,自己写了一个微信小程序,我的第一篇博客里分享了关于“图片的双指缩放和单指移动功能”的代码片段就是来自于这个小程序。今天,同样来分享一个更为复杂的“目录树”功能的实现思路。首先声明,该代码实际上是比较混乱的,后续并没有做简化和组件化,大家重点还是关注实现思路吧,这才精华。如果你真有需要,可尝试将它简化,并做成一个组件。
效果图:
以上是效果图,可通过搜索“随行文档”找到该小程序去体验效果,不过要自己保存内容才能体验出效果如何。
话不多说,步入正题 ----------------------------------------------------------------------------------------------------
先给出一个简单的树形结构:
一级目录
二级目录1
三级目录11
二级目录2
三级目录21
三级目录22
以上就是一个简单的目录树结构,初始化时肯定只想显示“一级目录”,其它层级都隐藏。即,如下:
一级目录
当手指触摸“一级目录”时,就会打开二级目录,就会变为如下这样:
一级目录
二级目录1
二级目录2
当手指触摸“二级目录”时,就会打开三级目录,以此类推...。
-------------------------------------------------------------------------------------------------------------------------------
后端数据库中,一般只用一张表来保存整个目录树;通常,前端接收到的保存了整个目录树的 JSON 数组是这样的:
[
{
id: xxx,
label: xxx,
child: {
id:xxx,
label: xxx,
child: {... }
}
},
........
]
可发现这是一个嵌套结构。如果所用的框架和技术支持动态生成标签,那么上面的这个嵌套结构就很方便的生成一个目录树并显示在页面。只需用div去嵌套的包裹这些目录树结点就可以了。演示如下:
<div>
<span>id值</span>
<span>label标题</span>
<div>
<span>id值</span>
<span>label标题</span>
<div>.....</div>
</div>
</div>
只要动态生成以上这种数据结构就可以生成一个目录树并显示在页面。不过我们现在说的是微信小程序生成目录树的方法,据我所了解到的(并不一定准确哦),开发微信小程序无法通过 JS 代码来动态生成标签结点,只能通过 wx:for 循环的生成结点的方式实现目录树了,那么以上的嵌套结构似乎就不可用了,需要将其转换成另一种数据结构。我的做法是把嵌套结构拆解成带顺序的上下结构,思路如下:
[
{
id: xxx,
label: xxx,
level: 1
child: true
},
{
id: xxx,
label: xxx,
level: 2,
child: true
},
{
id: xxx,
label: xxx,
level: 3,
child: false
},
........
]
以上的这种数据结构,数据里的每一个对象就是一个目录项,就很方便用 wx:for 来动态生成目录结点了。但这种数据结构在编码思路上与嵌套结构就大不相同了。首先强调对数组元素的顺序是有要求的。我们来用数据尝试保存开头举例提到的目录结构:
用一个数组保存该目录结构,目录项的顺序应该是这样的:
[
{一级目录},
{二级目录1},
{三级目录11},
{二级目录2},
{三级目录21},
{三级目录22}
]
顺序上要保证每一个目录项的子项紧跟着其父项。在编码上,目录项的展开和隐藏是通过 css 属性来控制。用户在对目录树进行展开与收闭时,就是通过操作上面的这个数组元素的 css 属性来控制数组元素的显示与隐藏,反应到界面就是目录树的目录项的展开与收闭。
以下是我将嵌套结构转化成带顺序的上下结构的代码,这段代码仅供参考,不能拿去就用。
以下方法有两个参数,nodes 就是从后端拿到的嵌套结构的数组,level 是顶层目录的层级,调用时一般赋值 1,即 handleAllNodes(nodes, 1)。
handleAllNodes(nodes, level){
let newLevel = level;
for(let node of nodes){
const obj = {}
obj.label = node.label;
obj.level = newLevel;
obj.questionId = node.questionId; // id 值</