Dan*_*man 7 javascript shadow-dom custom-element native-web-component
我花了一些时间进行搜索,但只看到太多常规的“遍历 DOM”博客或仅提升一个级别的答案getRootnode()
伪代码:
HTML
<element-x>
//# shadow-root
<element-y>
<element-z>
//# shadow-root
let container = this.closest('element-x');
</element-z>
</element-y>
</element-x>
Run Code Online (Sandbox Code Playgroud)
标准element.closest()功能并没有捅破阴影边界;
所以this.closest('element-x')返回null因为没有 <element-x>内<element-z>shadowDom
目标:
<element-x>从后代内部查找<element z>(任何嵌套级别)
必需的:
A(递归).closest()函数,走了(阴影)DOM小号和认定<element-x>
注意:元素可能有也可能没有 ShadowDOM(参见<element y>:仅 lightDOM)
我可以而且明天会自己做;只是想知道是否有聪明的头脑已经做到了。
资源:
这是以下答案中的未缩小代码:
closestElement(selector, base = this) {
function __closestFrom(el) {
if (!el || el === document || el === window) return null;
let found = el.closest(selector);
if (found)
return found;
else
__closestFrom(el.getRootNode().host);
}
return __closestFrom(base);
}
Run Code Online (Sandbox Code Playgroud)
我将其更改为 BaseElement 上的一个方法:
<element-x>
//# shadow-root
<element-y>
<element-z>
//# shadow-root
let container = this.closest('element-x');
</element-z>
</element-y>
</element-x>
Run Code Online (Sandbox Code Playgroud)
像这样的事情应该可以解决问题
function closestPassShadow(node, selector) {
if (!node) {
return null;
}
if (node instanceof ShadowRoot) {
return this.closestPassShadow(node.host, selector);
}
if (node instanceof HTMLElement) {
if (node.matches(selector)) {
return node;
} else {
return this.closestPassShadow(node.parentNode, selector);
}
}
return this.closestPassShadow(node.parentNode, selector);
}
Run Code Online (Sandbox Code Playgroud)
优秀的例子!我想贡献一个有细微差别的 TypeScript 版本——它在遍历影子根时遵循分配的槽位,这样你就可以在嵌套的、开槽的自定义元素链中找到最接近的匹配元素。这不是编写 TypeScript 的最奇特的方式,但它可以完成工作。
\n编辑:这段代码是 5 年前编写的,从那时起,typescript 本身已经取得了长足的进步。许多过去需要特殊处理的 JS 代码现在应该可以在 TypeScript 中使用 \xe2\x80\x9c 来工作\xe2\x80\x9d。这段代码可以而且很可能应该被简化。当然可以使用它,但我今天\xe2\x80\x99m 并不像 5 年前那样为它感到自豪:) 然而,我没有时间编辑它。
\nclosestElement(selector: string, base: Element = this) {\n function __closestFrom(el: Element | Window | Document): Element {\n if (!el || el === document || el === window) return null;\n if ((el as Slotable).assignedSlot) el = (el as Slotable).assignedSlot;\n let found = (el as Element).closest(selector);\n return found\n ? found\n : __closestFrom(((el as Element).getRootNode() as ShadowRoot).host);\n }\n return __closestFrom(base);\n}\nRun Code Online (Sandbox Code Playgroud)\nJS 中的等价物是:
\nclosestElement(selector, base = this) {\n function __closestFrom(el) {\n if (!el || el === document || el === window)\n return null;\n if (el.assignedSlot)\n el = el.assignedSlot;\n let found = el.closest(selector);\n return found\n ? found\n : __closestFrom(el.getRootNode().host);\n }\n return __closestFrom(base);\n}\nRun Code Online (Sandbox Code Playgroud)\n
小智 5
这与任何子(阴影)DOM 内部的.closest()相同
但是沿着 DOM穿越shadowroot 边界
针对(极端)缩小进行了优化
//declared as method on a Custom Element:
closestElement(
selector, // selector like in .closest()
base = this, // extra functionality to skip a parent
__Closest = (el, found = el && el.closest(selector)) =>
!el || el === document || el === window
? null // standard .closest() returns null for non-found selectors also
: found
? found // found a selector INside this element
: __Closest(el.getRootNode().host) // recursion!! break out to parent DOM
) {
return __Closest(base);
}
Run Code Online (Sandbox Code Playgroud)
注意:__Closest 函数被声明为“参数”以避免额外的let声明......更好地缩小,并防止您的 IDE 抱怨
从自定义元素内部调用:
<element-x>
//# shadow-root
<element-y>
<element-z>
//# shadow-root
let container = this.closestElement('element-x');
</element-z>
</element-y>
</element-x>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1816 次 |
| 最近记录: |