当所有子自定义元素都已连接时,如何具有"connectedCallback" [英] How to have a 'connectedCallback' for when all child custom elements have been connected

查看:123
本文介绍了当所有子自定义元素都已连接时,如何具有"connectedCallback"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Web Components v1.

I'm using Web Components v1.

假设有两个自定义元素:

Suppose two Custom Elements:

parent-element.html

<template id="parent-element">
    <child-element></child-element>
</template>

child-element.html

<template id="child-element">
<!-- some markup here -->
</template>

我正在尝试使用parent-element中的connectedCallback在连接时初始化整个父/子DOM结构,这需要与child-element中定义的方法进行交互.

I'm trying to use connectedCallback in parent-element to initialise the entire parent/child DOM structure when it is attached, which requires interaction with methods defined in child-element.

但是,似乎在为customElement解雇connectedCallback时未正确定义child-element:

However, it seems child-element isn't properly defined at the time connectedCallback gets fired for customElement:

parent-element.js

class parent_element extends HTMLElement {
    connectedCallback() {
        //shadow root created from template in constructor previously
        var el = this.shadow_root.querySelector("child-element");
        el.my_method();
    }
}

这是行不通的,因为elHTMLElement而不是预期的child-element.

This will not work, because el is an HTMLElement and not a child-element as expected.

一旦正确附加了模板中的所有子自定义元素,我就需要对parent-element进行回调.

I need a callback for parent-element once all child custom elements in its template have been properly attached.

The solution in this question does not seem to work; this.parentElement is null inside child-element connectedCallback().

ilmiont

推荐答案

在ShadowDOM模板中使用广告位元素.

Use slot elements in your ShadowDOM template.

以某种方式构建自定义元素,以便它们可以在任何上下文中生活,例如作为子元素或父元素,而与其他自定义元素没有任何依赖关系.这种方法将为您提供模块化设计,您可以在任何情况下利用自定义元素.

Build your custom elements in a way so that they can live in any context, like as a child or parent element, without having any dependencies with other custom-elements. This approach will give you a modular design in which you can utilize your custom-elements in any situation.

但是您仍然希望在存在子元素时执行某些操作,例如选择它们或在子元素上调用方法.

But you still want to do something whenever a child element is present, like selecting them or calling a method on a child.

要解决此问题, <slot> 元素具有被介绍.使用slot元素,您可以在ShadowDOM模板中创建占位符.只需将元素作为DOM中的子元素放在您的 custom-element 中,就可以使用这些占位符.然后,将子元素放置在<slot>元素放置的位置内.

To tackle this the <slot> element has been introduced. With slot elements you can create placeholders inside your ShadowDOM template. These placeholders can be used by simply placing an element inside your custom-element as a child in the DOM. The child element will then be placed inside the position where the <slot> element is placed.

但是您怎么知道占位符是否已填充元素?

广告位元素可以监听称为 .只要将一个元素(或多个元素)放置在slot元素的位置,就会触发该事件.

Slot elements can listen to a unique event called slotchange. This will be fired whenever an element is (or multiple elements are) placed on the position of the slot element.

在事件的侦听器内部,您可以使用 HTMLSlotElement.assignedNodes() HTMLSlotElement.assignedElements() 方法.这些将返回一个元素放置在slot中的数组.

Inside the listener of the event you can access all of the element in the placeholder with the HTMLSlotElement.assignedNodes() or HTMLSlotElement.assignedElements() methods. These return an array with the elements placed in the slot.

现在,您可以等待将孩子放置在插槽中,并对在场的孩子做一些事情.

Now you can wait for the children to be placed inside the slot and do something with the children that are present.

通过这种方式,您仅可以操作DOM,而让ShadowDOM任其单独工作.就像处理常规HTML元素一样.

This way allows you to only manipulate the DOM and leave the ShadowDOM alone and let it do its work. Just like you would do with regular HTML elements.

class ParentElement extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.innerHTML = '<h2>Parent Element</h2><slot></slot>';
    console.log("I'm a parent. I have slots.");
    
    // Select the slot element and listen for the slotchange event.
    const slot = this.shadowRoot.querySelector('slot');
    slot.addEventListener('slotchange', (event) => {
      const children = event.target.assignedElements();
      children.forEach(child => {
        if (child.tagName === 'CHILD-ELEMENT') {
          child.shout()
        }
      });
    });

  }
}

customElements.define('parent-element', ParentElement);

class ChildElement extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.innerHTML = '<h3>Child Element</h3>';
  }

  shout() {
    console.log("I'm a child, placed inside a slot.");
  }

}

customElements.define('child-element', ChildElement);

<parent-element>
  <child-element></child-element>
  <child-element></child-element>
  <child-element></child-element>
</parent-element>

这篇关于当所有子自定义元素都已连接时,如何具有"connectedCallback"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆