如何访问嵌套Web组件的锚点?

时间:2019-03-18 17:00:20

标签: javascript google-chrome web-component shadow-dom custom-element

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

$ echo 800001.1.pull | awk -F'.pull' '{ new=sprintf("%14s%s",$1,FS); gsub(/ /,0,new); print $0, new }'
800001.1.pull 000000800001.1.pull

$ echo 800001.12.345.pull | awk -F'.pull' '{ new=sprintf("%14s%s",$1,FS); gsub(/ /,0,new); print $0, new }'
800001.12.345.pull 0800001.12.345.pull

我创建的所有自定义元素都使用<body> <my-controller> <div> <my-list> <span> <my-item></my-item> </span> </my-list> </div> </my-controller> </body> 使用Shadow DOM。

我想从内部Web组件访问const root = super.attachShadow({mode: "open"}); root.appendChild(...);中的my-controller组件:

connectedCallback()


奇怪的是:我只能访问直接父级Web控件。


因此,如果在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.`); } } 上调用connectedCallback(),则可以到达<my-list>,但是如果在<my-controller>上调用connectedCallback(),则只能到达<my-item>。当我以<span>开始搜索时,我什至无法到达<my-list>

即使在调用<my-item>之后遍历DOM树,从connectedCallback()开始也无法超越<span>

这是故意的吗?

为什么可以从第一个嵌套的Web组件到达外部Web组件,而 从第二个嵌套的Web组件到达第一个嵌套Web组件呢?

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

3 个答案:

答案 0 :(得分:2)

当您定义带有Shadow DOM的Custom Element内容时,您将创建一个独特的DOM树。 Shadow DOM是一个没有根元素的DocumentFragment。

因此,仅通过parentElement属性将DOM向上移动,就无法达到其(直观的)祖先。

要访问Shadow DOM的宿主元素,请结合使用use getRootNode()host

通过<my-item>的{​​{1}}方法:

connectedCallback()

如果您想获得祖先,可以尝试使用此recursive function

答案 1 :(得分:1)

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

使用内部组件自定义事件(由外部组件捕获)更安全,更省心。

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

您可以执行以下操作:

子元素

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);
    }
  );
}

答案 2 :(得分:0)

ShadowRoot不是元素,并且ShadowRoot的{​​{1}}不是它的宿主元素。您需要照顾好他们。

parentNode