element tree

有一个懒加载的机构树,选中父节点的时候,子节点就全部选中并且禁止再次选择,这个功能能实现吗,怎么实现呢,能否有一个小demo

效果图如下:

img

<html>

<head>
  <style>
    /* 设置一些样式 */
    .tree {
      display: flex;
      flex-direction: column;
    }

    .node {
      display: flex;
      align-items: center;
      cursor: pointer;
    }

    .node>input[type="checkbox"] {
      margin-right: 8px;
    }
  </style>
</head>

<body>
  <!-- 在页面中添加一个机构树的容器 -->
  <div id="tree"></div>

  <script>
    // 定义一个机构树的节点数据模型
  class Node {
  constructor(id, name, children, onChange) {
    this.id = id;
    this.name = name;
    this.children = children || [];
    this.onChange = onChange;
  }

  setChecked(checked) {
    this.checked = checked;
    if (this.checkbox) {
      console.log('rrr', this.checkbox)
      this.checkbox.checked = checked;
    }
    if (this.onChange) {
      this.onChange(this);
    }
  }

  setDisabled(disabled) {
    this.disabled = disabled;
    if (this.checkbox) {
      this.checkbox.disabled = disabled;
    }
  }
}

function renderTree(node, parentNode) {
  if (!node) return;

  const nodeElement = document.createElement("div");
  nodeElement.className = "node";

  const checkbox = document.createElement("input");
  checkbox.type = "checkbox";
  checkbox.addEventListener("change", (event) => {
node.setChecked(event.target.checked);
if (event.target.checked) {
node.children.forEach((child) => {
child.setChecked(true);
child.setDisabled(true);
});
} else {
node.children.forEach((child) => {
child.setDisabled(false);
});
}
});
node.checkbox = checkbox;

const label = document.createElement("span");
label.textContent = node.name;

nodeElement.appendChild(checkbox);
nodeElement.appendChild(label);

if (node.children.length > 0) {
const childrenElement = document.createElement("div");
childrenElement.className = "tree";
node.children.forEach((child) => {
childrenElement.appendChild(renderTree(child, nodeElement));
});
nodeElement.appendChild(childrenElement);
}

parentNode.appendChild(nodeElement);

return nodeElement;
}

function createTree(rootNode, container) {
if (!rootNode || !(rootNode instanceof Node)) {
throw new Error("Invalid root node");
}
if (!container || !(container instanceof HTMLElement)) {
throw new Error("Invalid container element");
}

container.className = "tree";
return renderTree(rootNode, container);
}

const rootNode = new Node(
1,
"Root",
[
new Node(2, "Child 1", [
new Node(4, "Grandchild 1"),
new Node(5, "Grandchild 2"),
new Node(6, "Grandchild 3"),
]),
new Node(3, "Child 2", [
new Node(7, "Grandchild 4"),
new Node(8, "Grandchild 5"),
new Node(9, "Grandchild 6"),
])
],
(node) => {
console.log(`Node ${node.id} is ${node.checked ? "checked" : "unchecked"}`);
}
);

const treeElement = document.getElementById("tree");
createTree(rootNode, treeElement);
  </script>
</body>

</html>