Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何访问嵌套的web组件?_Javascript_Google Chrome_Web Component_Shadow Dom_Custom Element - Fatal编程技术网

Javascript 如何访问嵌套的web组件?

Javascript 如何访问嵌套的web组件?,javascript,google-chrome,web-component,shadow-dom,custom-element,Javascript,Google Chrome,Web Component,Shadow Dom,Custom Element,我正在为我的web组件实现一个Orchestrator模式,如下所示: 我创建的所有自定义元素都使用constroot=super.attachShadow{mode:open}使用阴影DOM;root.appendChild 我想从内部web组件访问connectedCallback中的我的控制器组件: 公共connectedCallback:无效 { 如果这个.断开连接 { 对于let node=this.parentElement;node;node=node.parentElement

我正在为我的web组件实现一个Orchestrator模式,如下所示:

我创建的所有自定义元素都使用constroot=super.attachShadow{mode:open}使用阴影DOM;root.appendChild

我想从内部web组件访问connectedCallback中的我的控制器组件:

公共connectedCallback:无效 { 如果这个.断开连接 { 对于let node=this.parentElement;node;node=node.parentElement 容器基的if节点实例 { 这。_service=node.GetServicethis; 打破 } 如果是,请重新设置此服务; else抛出新引用错误`${this.nodeName.toLowerCase}:在连接到文档时找不到主机元素。`; } } 奇怪的是:我只能访问直接的父web控件

所以,如果在上调用connectedCallback,我可以到达,但如果在上调用connectedCallback,我只能到达。当我开始搜索时,我甚至都够不着

即使在调用connectedCallback后遍历DOM树,我也无法超出从开始时的范围

这是故意的吗

为什么我可以从第一个嵌套的web组件访问外部web组件,而不能从第二个嵌套的web组件访问第一个嵌套的web组件


如何才能从任何嵌套级别完全访问DOM树?

通常认为内部/子元素能够从外部/父元素访问数据是不好的做法

使用由外部组件捕获的来自内部组件的自定义事件更安全,耦合更少

内部组件将调度一个事件,让外部元素知道它需要什么,然后外部组件可以调用函数或在内部组件上设置参数

您可以这样做:

子元素

connectedCallback{ 此.dispatchnew CustomEvent'request-service'; } 设置serviceval{ 这是._service=val; } 得到服务{ 退回此服务;
} 通常认为内部/子元素能够从外部/父元素访问数据是不好的做法

使用由外部组件捕获的来自内部组件的自定义事件更安全,耦合更少

内部组件将调度一个事件,让外部元素知道它需要什么,然后外部组件可以调用函数或在内部组件上设置参数

您可以这样做:

子元素

connectedCallback{ 此.dispatchnew CustomEvent'request-service'; } 设置serviceval{ 这是._service=val; } 得到服务{ 退回此服务; } 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)) {
  ...
}
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树。影子DOM是一个没有根元素的DocumentFragment

因此,仅通过parentElement属性向上遍历DOM无法到达其直观的祖先

要到达阴影DOM的主机元素,请改为与主机组合

来自的connectedCallback方法:


如果你想得到一个祖先,你可以试试这个

使用影子DOM定义自定义元素内容时,会创建一个独特的DOM树。影子DOM是一个没有根元素的DocumentFragment

因此,仅通过parentElement属性向上遍历DOM无法到达其直观的祖先

要到达阴影DOM的主机元素,请改为与主机组合

来自的connectedCallback方法:


如果你想得到一个祖先,你可以试试这个

可能是因为您使用的是阴影dom?否则就可以了。好吧,web组件应该始终使用阴影DOM。令人尴尬的是:当内部web组件的node.parentElement为null时,node.shadowRoot为null,并且仅适用于内部web组件。最外层的两个web组件的行为与预期一致。可能是因为您使用的是阴影dom?否则就可以了。好吧,web组件应该始终使用阴影DOM。令人尴尬的是:当内部web组件的node.parentElement为null时,node.shadowRoot为null,并且仅适用于内部web组件。最外层的两个web组件的行为符合预期。我不同意。事件驱动的方法是不利的:如果页面上有多个实例,那么它们都在侦听同一事件。您需要确保只在冒泡阶段捕获这些事件。我不认为体面的亲子关系有什么坏处。这就是DOM树的意义所在。探索
问题依然存在:为什么嵌套在层次结构深处的web控件与外部两个web控件的行为不同?请不同意。但是,当你决定让父母和孩子彼此了解得比他们应该了解的更多时,你就会制造出一团意大利面和其他任何地方都无法使用的部件。您的代码可以很容易地找出事件的来源。如果不能,那么你应该重构它。一旦你允许一个孩子深入到它的父母那里,你就允许代码被放在错误的组件中,并且摆脱这种混乱是非常困难的。不,这取决于设计。例如,如果没有元素作为其父元素,元素就无法生存。这是一种紧密的关系,也是一种要求。在父子关系中,如果没有父母提供服务,那么孩子就没有意义。另一方面,使用事件,您甚至不能保证有一个父级为其子级提供服务。如果严格的父子关系要求是您想要的,那么遵循这条路线并没有什么不好的做法。实际上,元素可以位于父元素之外。但是,如果我的代码具有DOM依赖关系,只是为了将数据放入子元素中,我会重写它。让一个元素的脚本依赖于某个特定父元素的脚本的想法让我不寒而栗。我只是提到一个具体的、被广泛理解的做法。如果你想写两个紧密耦合的元素,这是你的选择。但我认为这是个坏主意。只有一个坏习惯,那就是不练习。本质上意味着没有好的实践。我不同意。事件驱动的方法是不利的:如果页面上有多个实例,那么它们都在侦听同一事件。您需要确保只在冒泡阶段捕获这些事件。我不认为体面的亲子关系有什么坏处。这就是DOM树的意义所在。问题仍然存在:为什么嵌套在层次结构深处的web控件与外部两个web控件的行为不同?请不同意。但是,当你决定让父母和孩子彼此了解得比他们应该了解的更多时,你就会制造出一团意大利面和其他任何地方都无法使用的部件。您的代码可以很容易地找出事件的来源。如果不能,那么你应该重构它。一旦你允许一个孩子深入到它的父母那里,你就允许代码被放在错误的组件中,并且摆脱这种混乱是非常困难的。不,这取决于设计。例如,如果没有元素作为其父元素,元素就无法生存。这是一种紧密的关系,也是一种要求。在父子关系中,如果没有父母提供服务,那么孩子就没有意义。另一方面,使用事件,您甚至不能保证有一个父级为其子级提供服务。如果严格的父子关系要求是您想要的,那么遵循这条路线并没有什么不好的做法。实际上,元素可以位于父元素之外。但是,如果我的代码具有DOM依赖关系,只是为了将数据放入子元素中,我会重写它。让一个元素的脚本依赖于某个特定父元素的脚本的想法让我不寒而栗。我只是提到一个具体的、被广泛理解的做法。如果你想写两个紧密耦合的元素,这是你的选择。但我认为这是个坏主意。只有一个坏习惯,那就是不练习。本质上意味着没有好的实践。我想在这里分享我在研究了您关于getRootNode返回值的优秀评论后学到的知识:。阅读文档时,返回值的类型可能会显得模糊,但该注释很好地说明了这一点。我想在这里分享我在研究了您关于getRootNode返回值的优秀注释后学到的知识:。在阅读文档时,返回值的类型可能看起来很模糊,但该注释很好地说明了这一点。