我花了一些时间搜索,但只看到太多常规的“走DOM”博客或答案只有一个级别UP与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并找到<element-x>
注意:元素可能有也可能没有ShadowDOM(参见<element y>
:只有lightDOM)
我可以而且明天会自己做;只是想知道是否有一些聪明的头脑已经做到了。
资源:
这是以下答案中的UNminified代码:
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);
}
这与任何子(阴影)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>
很好的例子!想要提供一个具有细微差别的TypeScript版本 - 它在遍历阴影根时遵循assignedSlot,因此您可以在嵌套的,开槽的自定义元素链中找到最接近的匹配元素。这不是编写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);
}