代码之家  ›  专栏  ›  技术社区  ›  akc42

如何遍历在正确位置开槽的DOM picking节点

  •  0
  • akc42  · 技术社区  · 6 年前

    我正在制作一个“psuedo”,“super”形式的自定义元素。我想遍历这些节点,以便查找符合特定条件的节点(一个是它们有一个方法 function 打电话 validate ,另一个是他们有 name value ). 在我的穿越中我想

    • 避免元素的子节点转移到元素shadowroot中的槽中。
    • 遍历元素上的阴影根,并在该遍历中拾取已传输到元素内插槽的元素。
    • 不遍历与上面提到的条件匹配的元素的子元素或阴影根。

    似乎有两种可能的方法。

    1. 创建一个“treewalker”,并使用它遍历它找到的节点。
    2. 只需对以下调用使用Node API Node.hasChildNodes() Node.childNodes

    但是,我找不到任何关于这两种可能性的文档来解释时隙内容的情况。这些文档通常忽略插槽和时隙内容的任何提及,可能是因为它们是在插槽成为规范的一部分之前编写的。

    很明显 Slot.assignedNodes() 方法,在遍历shadowRoot时,我可以使用该方法来查找槽中的内容(尽管即使该方法的文档在可选的 flatten

    那么,形成上述行为的最佳方式是什么?有人能给我一些线索吗?

    1 回复  |  直到 6 年前
        1
  •  0
  •   akc42    6 年前

    我最终发现最好的方法是手动操作。测试的关键是 node.assignedSlot 当元素被分配给槽时不为空,因此可以在扫描子元素时使用此选项,以便在将子元素分配给槽时忽略它们(并在扫描时包含它们 slot.assignedNodes()

    这是一个带有 walk 用于遍历所提供元素的默认函数。 criteria 是每个节点的回调函数,调用者可以使用该函数检查节点是否满足查找的条件(请参见问题),因此不扫描子节点。

    function _walk(node,criteria, slot) {
      if (node.assignedSlot === null || node.assignedSlot === slot) {
        if (node.localName === 'slot') {
          const assignedNodes = node.assignedNodes();
          if (assignedNodes.length  === 0) {
            _walkA(node.children, criteria);
          } else {
            _walkA(assignedNodes.filter(n => n.nodeType === Node.ELEMENT_NODE), criteria, node);
          }
        } else if (!criteria(node)) {
          if (customElements.get(node.localName)) _walkA(node.shadowRoot.children,criteria);
          _walkA(node.children, criteria);
        }
      }
    }
    function _walkA(nodes,criteria, slot) {
      for (let n of nodes) {
        _walk(n,criteria, slot);
      }
    }
    export default function walk(walknode, criteria) {
      _walk(walknode,criteria,null);
    }