E3.16.2tree parent mixed from children设计
部分子节点被选中时父节点需显示中间态
别名: 树的中间态 · bubble mixed · 子变父变
概念解释
在树上,子节点的勾选一变,父节点的显示必须立刻重算:全部子节点都勾则为勾,全部不勾则为空,其余为中间态。这是向上冒泡(bubble-up)。它和「勾父则勾子」方向相反:一个改集合往下写,一个改摘要往上读。用户在叶子上勾了两个、没勾第三个,折起这一支时,父级必须说出混合,而不能仍停在刚才的全勾或全空。
中间态在这里是树的实时摘要,随着每一次叶子点击更新,不是打开面板时算一次的静态标记。
机制
折叠把叶子藏起来,父级成为该支唯一可见的选择控件。若父级不随叶子更新,折叠等于把过期摘要钉在树上。人会在折叠后以为整支已加入或整支未加入,提交一份和展开时不同的集合。冒泡必须沿祖先链走完:叶子变 → 父变 → 祖变,否则只修了相邻一层,顶层仍撒谎。
冒泡是派生,不要把中间态写回叶子。叶子保持自己的布尔,父级显示由子集合算出来。和向下联动接上时,勾父会把子写成全勾,冒泡随即把父写成勾——两向在这一拍对齐。只勾部分叶子则父停在中间,不会反过来把其余叶子强行勾上;那个强行是向下联动的职责,只在用户点父级时发生。
边界
父节点作为独立对象被选中、子节点全空时,父级应显示已选而不是空——冒泡规则要承认「父自身」这一位,否则只选父会看起来像没选。虚拟滚动中未挂载的叶子仍要参与计算,否则滚动进视野才突然把父级改成混合。过滤把部分叶子藏起时,冒泡按真实集合还是按可见集合,须与向下联动的范围声明一致。动画若慢于点击,连续点几片叶子会看到父级在过期态上跳动,摘要应同步在同一帧更新。
怎么落地
- 每次叶子勾选变化,沿祖先重算空 / 混 / 满,折叠前后显示一致。
- 不要把中间态当作可写入叶子的值;叶子只认自己的布尔。
- 未渲染和被过滤的节点仍进入计算,范围与向下联动相同。
- 验证:展开勾两片叶子,折叠。父级必须是中间态。再勾第三片使该支齐全,父级变成勾。折叠过程中摘要若不变,冒泡就断了。