如何访问嵌套 Web 组件的锚点?
How to access anchestor of nested web components?
我正在为我的 Web 组件实施 Orchestrator 模式,如下所示:
<body>
<my-controller>
<div>
<my-list>
<span>
<my-item></my-item>
</span>
</my-list>
</div>
</my-controller>
</body>
我创建的所有自定义元素都使用阴影 DOM 使用 const root = super.attachShadow({mode: "open"}); root.appendChild(...);
。
我想从我的内部 Web 组件到达 connectedCallback()
中的 my-controller
组件:
public connectedCallback(): void
{
if (this.isConnected)
{
for (let node = this.parentElement; node; node = node.parentElement)
if (node instanceof ContainerBase)
{
this._service = (<ContainerBase>node).GetService(this);
break;
}
if (this._service) this.Reset();
else throw new ReferenceError(`${this.nodeName.toLowerCase()}: Couldn't find host element while connecting to document.`);
}
}
奇怪的是:我只能到达直接的父级web控件。
因此,如果在 <my-list>
上调用 connectedCallback()
,我可以到达 <my-controller>
,但如果在 <my-item>
上调用 connectedCallback()
,我只能到达 <span>
。当我使用 <my-item>
开始搜索时,我什至无法到达 <my-list>
。
即使我在调用 connectedCallback()
之后遍历 DOM 树,当我从 <my-item>
开始时,我也无法超过 <span>
。
这是故意的吗?
为什么 可以 我从第一个嵌套的 Web 组件到达外部 Web 组件而我 不能 从第二个嵌套的 Web 组件到达第一个嵌套的 Web 组件嵌套一个?
我怎样才能从任何嵌套级别完全向上 DOM 树?
通常认为 inner/child 元素能够从 outer/parent 元素访问数据是不好的做法。
使用由外部组件捕获的内部组件的自定义事件更安全且耦合度更低。
内部组件会派发一个事件让外部元素知道它需要一些东西,然后外部组件可以调用内部组件的函数或设置参数。
你可以这样做:
子元素
connectedCallback() {
this.dispatch(new CustomEvent('request-service'));
}
set service(val) {
this._service = val;
}
get service() {
return this._service;
}
服务元素:
constructor() {
super();
this.addEventListener('request-service',
evt => {
evt.target.service = this.GetService(evt.target);
}
);
}
ShadowRoot
不是元素,ShadowRoot
的 parentNode
不是它的宿主元素。你需要照顾他们。
function shadowIncludingParentElement(node) {
if (node.parentElement)
return node.parentElement;
if (!node.parentNode)
return null;
if (node.parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE)
return node.parentNode.host;
return null;
}
...
for (let node = this.parentElement; node;
node = shadowIncludingParentElement(node)) {
...
}
当您使用阴影 DOM 定义自定义元素内容时,您会创建一个独特的 DOM 树。 Shadow DOM 是一个没有根元素的 DocumentFragment。
因此,您无法通过 DOM 向上 parentElement
属性.
简单地到达其(直观的)祖先
要到达 Shadow DOM 的宿主元素,而不是 结合 host
。
来自<my-item>
的connectedCallback()
方法:
connectedCallback() {
var parent = this.getRootNode().host
console.log( parent.localNode ) // my-list
}
如果你想得到一个祖先,你可以试试这个。
我正在为我的 Web 组件实施 Orchestrator 模式,如下所示:
<body>
<my-controller>
<div>
<my-list>
<span>
<my-item></my-item>
</span>
</my-list>
</div>
</my-controller>
</body>
我创建的所有自定义元素都使用阴影 DOM 使用 const root = super.attachShadow({mode: "open"}); root.appendChild(...);
。
我想从我的内部 Web 组件到达 connectedCallback()
中的 my-controller
组件:
public connectedCallback(): void
{
if (this.isConnected)
{
for (let node = this.parentElement; node; node = node.parentElement)
if (node instanceof ContainerBase)
{
this._service = (<ContainerBase>node).GetService(this);
break;
}
if (this._service) this.Reset();
else throw new ReferenceError(`${this.nodeName.toLowerCase()}: Couldn't find host element while connecting to document.`);
}
}
奇怪的是:我只能到达直接的父级web控件。
因此,如果在 <my-list>
上调用 connectedCallback()
,我可以到达 <my-controller>
,但如果在 <my-item>
上调用 connectedCallback()
,我只能到达 <span>
。当我使用 <my-item>
开始搜索时,我什至无法到达 <my-list>
。
即使我在调用 connectedCallback()
之后遍历 DOM 树,当我从 <my-item>
开始时,我也无法超过 <span>
。
这是故意的吗?
为什么 可以 我从第一个嵌套的 Web 组件到达外部 Web 组件而我 不能 从第二个嵌套的 Web 组件到达第一个嵌套的 Web 组件嵌套一个?
我怎样才能从任何嵌套级别完全向上 DOM 树?
通常认为 inner/child 元素能够从 outer/parent 元素访问数据是不好的做法。
使用由外部组件捕获的内部组件的自定义事件更安全且耦合度更低。
内部组件会派发一个事件让外部元素知道它需要一些东西,然后外部组件可以调用内部组件的函数或设置参数。
你可以这样做:
子元素
connectedCallback() {
this.dispatch(new CustomEvent('request-service'));
}
set service(val) {
this._service = val;
}
get service() {
return this._service;
}
服务元素:
constructor() {
super();
this.addEventListener('request-service',
evt => {
evt.target.service = this.GetService(evt.target);
}
);
}
ShadowRoot
不是元素,ShadowRoot
的 parentNode
不是它的宿主元素。你需要照顾他们。
function shadowIncludingParentElement(node) {
if (node.parentElement)
return node.parentElement;
if (!node.parentNode)
return null;
if (node.parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE)
return node.parentNode.host;
return null;
}
...
for (let node = this.parentElement; node;
node = shadowIncludingParentElement(node)) {
...
}
当您使用阴影 DOM 定义自定义元素内容时,您会创建一个独特的 DOM 树。 Shadow DOM 是一个没有根元素的 DocumentFragment。
因此,您无法通过 DOM 向上 parentElement
属性.
要到达 Shadow DOM 的宿主元素,而不是 host
。
来自<my-item>
的connectedCallback()
方法:
connectedCallback() {
var parent = this.getRootNode().host
console.log( parent.localNode ) // my-list
}
如果你想得到一个祖先,你可以试试这个