举例解释:
以闽侯县为例,闽侯县为一个节点,福州市、福建省为闽侯县的父节点,上街镇、南屿镇为闽侯县的子节点。在该图中,福建省、福州市、闽侯县均为分支节点,上街镇、南屿镇均为叶子节点。
2. 多选树
具备2个功能:
展开/收起:可展开或收起其子节点(本文实现的是只能展开一级,且无影象功能);选择:通过复选框进行复选。当选中某节点时,其子节点均当选中;反之均不当选中。
当某节点所在层级均当选中时,其上级自动选中;当某节点所在层级均不当选中时,其上级自动取消勾选;当某节点所在层级选中情形不等时,其上级呈待选中状态。
以上解释恐非标准说法,但为了读者便于理解本文可先代入,有缺点也欢迎大家示正!
三、整体思路
以中继器包裹节点,通过更新中继器中的一些列来改变节点形态(如位置、展开/收起按钮展示、多选框状态),根据中继器中的列“id”可知道其父节点、子节点有哪些。
展开/收起实现:点击时获取节点id,通过判断id能够获取其子节点有哪些,通过更新行操作展示或收起其所有子节点。选择实现:中继器中记录节点的子节点总数和选中的子节点数量。点击时获取节点id,通过判断id能够获取其父节点、子节点有哪些。当该节点选中时,其子节点均当选中;其父节点选中的子节点数量增加,当父节点的子节点总数和选中的子节点数量相同时,父节点即当选中。当该节点取消选中时,其子节点均取消选中;其父节点选中的子节点数量减少,当父节点选中的子节点数量为0时,父节点即取消选中。四、根本元件1. 主体元件文本标签“层级名称”:用于展示你要展示的内容。图标“triangle”:一个箭头造型的iconfont(也可以是个图片),作为展开/收起的状态展示。复选框:一个动态面板,有“未勾选”、“部分选中”、“已勾选”3种状态。当该节点的子节点均选中时,复选框状态为“已勾选”;当该节点的子节点部分选中时,复选框状态为“部分选中”;当该节点的子节点均未当选中时,复选框状态为“未勾选”。叶子节点则没有“部分选中”的状态。动态面板“主体”:用于包裹上述元件,便于触发triangle的交互。中继器:用于包裹动态面板“主体”。2. 赞助元件二级按钮、三级按钮、四级按钮、五级按钮均为赞助按钮(终极隐蔽起来即可),点击某层级的复选框时会触发对应层级的赞助元件,这是为了让交互看起来更加清晰。
五、详细实现1. 中继器初始化事情
1)中继器字段定义
id:节点编号。1级节点2位、2级节点4位…n级节点2n位。从01开始编号,前2(n-1)位为上级节点编号,如上图闽侯县的编号为010101,其下级节点上街镇、南屿镇的编号分别为01010101、01010102。grade:节点层级。1级节点为1,2级节点为2…n级节点为n。children:节点的叶子节点总数。如上图闽侯县、福州市、福建省的children均为2(上街镇、南屿镇)。节点的children为其下级节点的children之和。
content:节点内容。visible:节点是否可见。1为可见,0为不可见。triangle:箭头是否可见。1为可见,0为不可见。point:箭头方向。1为展开(向下),0为收起(向右)。select:节点是否当选中。2为其子节点选中,1为其子节点部分当选中,0为未当选中。childrenSelect:节点的叶子节点中当选中的数量。2)中继器交互
① 每项加载时,设置“层级名称”为中继器的列“content”。
根据“grade”的值判断“主体”的位置(此处仅5级,读者可自行拓展)。
根据“triangle”的值判断是否展示箭头。
根据“point”的值判断箭头方向。
根据“select”的值判断选中状态。
每个判断类型的第一个条件为if,这是由于每个判断类型都需被实行。
2)载入时,将“visible”为1的行添加筛选。
2. 展开收起
1)思路:点击箭头时判断箭头方向,方向在展开、收起间切换,若要展开就将其子节点的visible设为1,反之设为0。
子节点如何界定:当前行子节点的id是在当前行id的根本上连续编号的,故获取当前行的id位数即可得知其他节点id的前几位须要和该行id相同,即TargetItem.id.substr(0,grade2)==id。上述界定办法同样适用于当前行本身,以是还需剔除当前行,即TargetItem.grade!=grade。要遍历所有行必须用TargetItem而非Item。2)详细实现:单击箭头时:
① 获取该行的id、grade分别存于全局变量id、grade(本文所有全局变量的设置均是为了便于调试)。
② 判断该行的point的值:
若为1:更新当前行的point=0,更新当前行子节点[[TargetItem.id.substr(0,grade2)==id && TargetItem.grade!=grade]]的visible==0若为0:更新当前行的point=1,更新当前行下一级的visible==1(若想要其子节点全部展开即和为1时的规则一样即可)3)设置动态面板“主体”单击时触发箭头的单击交互。
3. 向下全选
1)思路:点击复选框时判断选中状态,若须要取消勾选则将当前行和其子节点的select设为2,反之设为0。
2)详细实现:单击复选框时:
① 获取该行的id、grade分别存于全局变量id、grade。
② 判断面板状态:
若非已勾选(即须要取消勾选):更新当前行及其子节点[[TargetItem.id.substr(0,grade2)==id]]的select==2、childrenSelect==TargetItem.children(向上选中时利用)若为已勾选(即须要勾选):更新当前行及其子节点[[TargetItem.id.substr(0,grade2)==id]]的select==0、childrenSelect==0(向上选中时利用)4. 向上选中1)思路
点击复选框时判断选中状态,若须要选中则将其父节点的“childrenSelect”的值加上多出来的叶子节点数量(当前行“children”的值-当前行“childrenSelect”的值),反之将其父节点的“childrenSelect”的值减去当前行“children”的值。
每次实行完以上时判断“childrenSelect”的值,若与其“children”相等,就解释这个节点的子节点都当选中了;若=0,就解释这个节点的子节点均未当选中;否则即其子节点部分当选中。
① 为了提高易读性,把除设置变量以外的交互都写在了赞助元件中。
② 由于叶子节点的children==0且无子节点,故点击叶子节点的复选框时,其父节点“childrenSelect”的值直接加/减1即可。
③ 父节点如何界定:当前行的id是在其父节点id的根本上连续编号的,故获取检索行的id位数即可得知当前行id的前几位须要和检索行id相同,即TargetItem.id==id.substr(0,grade2)。
由于暂未找到Axure自动轮询的方法,故须对每级节点单独写交互。
若当前行为3级节点,仅1级节点、2级节点均为其父节点,即TargetItem.id==id.substr(0,2) || TargetItem.id==id.substr(0,4)。
若当前行为4级节点,仅1级节点、2级节点、3级节点均为其父节点,即TargetItem.id==id.substr(0,2) || TargetItem.id==id.substr(0,4) || TargetItem.id==id.substr(0,6)…
2)详细实现
① 单击复选框时获取该行的select、children、childrenSelect分别存于全局变量select、children、childrenSelect,触发4个赞助元件的单击事宜。
② 二级按钮交互
若为分支节点,且非选中状态(即须要勾选。判断条件:select!=2 并且 grade==2 并且 children!=0):
更新当前行父节点[[TargetItem.id==id.substr(0,2)]]的select==1、childrenSelect==TargetItem.childrenSelect+children-childrenSelect;
更新“children==childrenSelect”的非叶子节点所在行[[TargetItem.children==TargetItem.childrenSelect && TargetItem.children!=0]]的select==2。
若为叶子节点,且非选中状态(即须要勾选)。差异仅在于判断条件的children==0,更新当前行父节点的childrenSelect==TargetItem.childrenSelect+1。
实际上,叶子节点的select只有0、2两种状态。
若为分支节点,且为选中状态,即须要取消勾选。
判断条件:select==2 并且 grade==2 并且 children!=0):
更新当前行父节点[[TargetItem.id==id.substr(0,2)]]的select==1、childrenSelect==TargetItem.childrenSelect-children。
更新“childrenSelect==0”的非叶子节点所在行[[TargetItem.children!=0 && TargetItem.childrenSelect==0]]的select==0。
若为叶子节点,且为选中状态(即须要取消勾选)。差异仅在于判断条件的children==0,更新当前行父节点的childrenSelect==TargetItem.childrenSelect-1
③ 三级按钮交互:与二级按钮交互的差异在于单击时的判断条件上(grade==3)和当前行父节点的判断条件上,三级按钮确当前行父节点为[[TargetItem.xuhao==id.substr(0,2) || TargetItem.xuhao==id.substr(0,4)]]
其他级按钮以此类推。
六、写在后面的话1. 不敷之处/可优化的点
由于该设计为工具类,应只管即便减少利用者的利用本钱。中继器中可不填写grade,grade可通过id位数来确定。
仅支持5层的树,若想要更高层级需读者自行写交互(但在理解的根本上复制修正即可,在箭头的交互上已经实现了无层级差异的)。
每层仅支持99个节点,若需更多节点要修正id编号及交互。
还未实现选择后的回填效果,如“送货地区”栏选择了多个省、市后点击确认把选择的省、市回填到输入框中。
2. 碰着的坑
赞助元件的单击交互中,一开始是直接判断复选框的状态变革,但永久获取到的状态都是“!=选中”(纵然区分为“==未选中”或“==部分选中”也都是“!=选中”),故改成了判断全局变量“select”的值。
复选框的交互中,一开始想通过以下办法实现遍历,但无法触发状态变革时的交互,故改成了在单击时的交互中做处理(如此更麻烦的,且无法实现无层级差异的处理)。
中继器中不是记录叶子节点的数量,而是记录直接下级的总数(这样既好打算,后期也好掩护)。单击时设置一些全局变量并修合法前行“select”的值,状态变革时根据状态修合法前行直接上级的已选中直接下级数量,当已选中直接下级数量==直接下级总数时,勾选当前行。3. 鸣谢本人在设计过程中部分思路参考了《Axure教程:Axure中继器实现动态树构造控件详解》(作者:Pershing)、《Axure教程:可增编削的树型构造》(作者:梓贤vigo),感谢大佬们!
欢迎大家示正问题或发起!
万分感谢!
本文由 @Air 原创发布于大家都是产品经理,未经容许,禁止转载
题图来自 Pexels,基于 CC0 协议