在很多系统中都有选择联系人的需求,市面上也没什么好的参照,产品经理看企业微信的选人挺好用的,就说参照这个做一个吧。。。 算了,还是试着做吧,企业微信的选人的确做的挺好,不得不佩服。 先看看效果图吧,多层级无规律的嵌套都能搞定
整个界面分为三部分:
最上面的返回上一层按钮
中间的显示部门、人员的列表
最下面显示和操作已选人员的 footer。
为什么加一个返回上一层按钮呢?
我也觉得比较丑,但小程序无法直接控制左上角返回键(自定义 Title 貌似可以,没试过),点左上角的返回箭头的话就退出选人控件到上个页面了。
我们的需求是点击一个文件夹,通过刷新当前列表进入下一级目录,感觉像是又进了一个页面,但其实并没有,只是列表的数据变化了。由此实现不定层级、无规律的部门和人员嵌套的支持。
比如先点击了首屏数据的第二个 item,它的 index 是 1 ,就将 1 存入 indexList ;返回上一层时将最后一个元素删除。
当勾选了某个人或部门时,会在底部的框中显示所有已选人员或部门的名字,当文字超过屏幕宽度时可以向右无限滑动,底部 footer 始终保持一行。
最终选择的人以底部 footer 里显示的为准,点击确定时根据业务需要将已选人员数据发送给需要的界面。
二、功能逻辑分析先看看数据格式
{ id: TEACHER_ID, name: '教师', parentId: '', checked: false, isPeople: false, children: [ { id: TEACHER_DEPARTMENT_ID, name: '部门', parentId: 'teacher', checked: false, isPeople: false, children: [] }, { id: TEACHER_SUBJECT_ID, name: '学科', parentId: 'teacher', checked: false, isPeople: false, children: [] }, { id: TEACHER_GRADECLASS_ID, name: '年级班级', parentId: 'teacher', checked: false, isPeople: false, children: [] }, ] }所有的数据组成一个数据树,子节点嵌套在父节点下。
id, name 不说了,parentId 指明它的父节点,children 包含它的所有子节点,checked 用来判断勾选状态,isPeople 判断是部门还是人员,因为两者的图标不一样。
注意:
本控件采用了数据分步加载的模式,除了最上层固定的几个分类,其他的每层数据都是点击具体的部门后才去请求服务器加载本部门下的数据的,然后再拼接到原始数据树上。这样可以提高加载速度,提升用户体验。
我也试了一次性把所有数据都拉下来,一是太慢,得三五秒,二是数据量太大的话(我这里应该是超过1000,阈值多少没测过),setData() 的时候就会报错:
超过最大长度了。。。所以只能分步加载数据。
当然如果你的数据量小,几十人或几百人,也可以选择一次性加载。
这个控件逻辑上还是比较复杂的,要考虑的细节太多……下面梳理一下主要的逻辑点
主要逻辑点 1. 需要一个数组存储所有被点击的部门在当前列表的索引 index ,这里用 indexList 表示点击某个部门进入下一层目录时,将被点击部门的 index 索引 push 进 indexList 中。点击返回上一层按钮时,删除 indexList 中最后一个元素。
2. 要动态的更新当前列表 currentList每进入新的一层,或返回上一层,都需要刷新 currentList 来实现页面的更新。知道下一层数据很容易,直接取被点击 item 的 children 赋值给 currentList 即可。
但如何还原上一层的数据呢?
第一点记录的 indexList 就发挥作用了,原始数据树为 originalList,循环遍历 indexList ,根据索引依次取出每层的 currentList 直到 indexList 的最后一个元素,就得到了返回上一层需要显示的数据。
3. 每一次勾选或取消选中都要更新原始的数据树 originalList