树控件 indeterminate

介绍

树控件(Tree Control)是一种常见的用户界面组件,用于展示层次结构的数据。在树控件中,每个节点都可以包含子节点,从而形成树状结构。在树控件中,有一种特殊的状态叫做"indeterminate",表示节点的选中状态不确定。

indeterminate 状态

在树控件中,节点的选中状态通常有两个值:选中(checked)和未选中(unchecked)。但是,有时候我们需要表示一个节点的选中状态不确定,即部分选中的状态。这个状态就是 indeterminate(半选中)。

当一个父节点的某个子节点被选中时,该父节点处于 indeterminate 状态;当一个父节点的所有子节点都被选中时,该父节点处于选中状态;当一个父节点的所有子节点都未被选中时,该父节点处于未选中状态。

代码示例

下面是一个使用 HTML 和 JavaScript 实现树控件的示例代码:

<div id="tree">
  <ul>
    <li>
      <input type="checkbox" id="node1" />
      <label for="node1">Node 1</label>
      <ul>
        <li>
          <input type="checkbox" id="node1-1" />
          <label for="node1-1">Node 1.1</label>
        </li>
        <li>
          <input type="checkbox" id="node1-2" />
          <label for="node1-2">Node 1.2</label>
        </li>
      </ul>
    </li>
    <li>
      <input type="checkbox" id="node2" />
      <label for="node2">Node 2</label>
    </li>
  </ul>
</div>

<script>
  // 获取所有父节点
  const parents = document.querySelectorAll("#tree input[type='checkbox']");

  // 设置父节点的 indeterminate 状态
  function setIndeterminateState(node) {
    if (node.indeterminate) {
      node.removeAttribute("indeterminate");
    } else {
      node.indeterminate = true;
    }
  }

  // 点击子节点时,更新父节点的 indeterminate 状态
  function updateParentIndeterminateState(node) {
    const parent = node.parentNode.parentNode.previousElementSibling;
    const siblings = Array.from(parent.nextElementSibling.querySelectorAll("input[type='checkbox']"));
    const checkedSiblings = siblings.filter(node => node.checked);
    if (checkedSiblings.length > 0 && checkedSiblings.length < siblings.length) {
      setIndeterminateState(parent);
    } else {
      parent.indeterminate = false;
      parent.checked = checkedSiblings.length === siblings.length;
    }
    if (parent.parentNode.parentNode) {
      updateParentIndeterminateState(parent);
    }
  }

  // 点击父节点时,更新子节点的选中状态
  function updateChildrenCheckedState(node) {
    const children = Array.from(node.nextElementSibling.querySelectorAll("input[type='checkbox']"));
    children.forEach(child => {
      child.checked = node.checked;
      updateChildrenCheckedState(child);
    });
  }

  // 添加事件监听器
  parents.forEach(parent => {
    parent.addEventListener("click", function() {
      updateChildrenCheckedState(this);
      updateParentIndeterminateState(this);
    });
  });
</script>

流程图

下面是实现树控件 indeterminate 状态的流程图:

flowchart TD
  A[点击子节点] --> B{子节点选中状态}
  B -- 部分选中 --> C(设置父节点为 indeterminate)
  C --> D[如果父节点有父节点]
  D -- 递归 --> A
  B -- 全部选中 --> E(设置父节点为 checked)
  E --> D
  B -- 未选中 --> F(取消父节点的 indeterminate 状态)
  F --> D

饼状图

下面是一个使用 mermaid 语法绘制的饼状图:

pie
  "选中" : 70
  "未选中" : 20
  "部分选中" : 10

总结

树控件是一种常见的用户界面组件,用于展示层次结构的数据。其中,indeterminate 状态表示节点的选中状态不确定。在代码示例中,我们使用 HTML 和 JavaScript 实现了树控件,并演示了如何实现 indeterminate 状态