我花了一些时间进行搜索,但只看到太多常规的“走在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>
标准element.closest()
函数不会不穿透阴影边界;
因此this.closest('element-x')
返回null
是因为<element-x>
shadowDom中没有否 <element-z>
目标:
从后代<element-x>
(任何嵌套级别)中找到<element z>
必填:
一个(递归).closest()
函数,用于遍历(阴影)DOM s 并找到<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);
return found ? found : __closestFrom(el.getRootNode().host);
}
return __closestFrom(base);
}
答案 0 :(得分:2)
这与任何子(阴影)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);
}
注意:__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>
答案 1 :(得分:0)
优秀的例子!希望提供一个具有细微差别的TypeScript版本-在遍历阴影根时遵循AssignSlot,因此您可以在嵌套的,带槽的自定义元素链中找到最接近的匹配元素。这不是编写TypeScript的最理想的方法,但是可以完成工作。
closestElement(selector: string, base: Element = this) {
function __closestFrom(el: Element | Window | Document): Element {
if (!el || el === document || el === window) return null;
if ((el as Slotable).assignedSlot) el = (el as Slotable).assignedSlot;
let found = (el as Element).closest(selector);
return found
? found
: __closestFrom(((el as Element).getRootNode() as ShadowRoot).host);
}
return __closestFrom(base);
}
JS中的等效项是:
closestElement(selector, base = this) {
function __closestFrom(el) {
if (!el || el === document || el === window)
return null;
if (el.assignedSlot)
el = el.assignedSlot;
let found = el.closest(selector);
return found
? found
: __closestFrom(el.getRootNode().host);
}
return __closestFrom(base);
}
答案 2 :(得分:0)
这样的事情应该可以解决问题
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);
}