this.getAttribute 在违反规范的情况下无法在 Web 组件中工作

Tac*_*ack 4 html javascript web-component custom-element native-web-component

我正在制作一个 Web 组件,它将显示“Hello {name}!” 从哪里来。{name}name="foo"当我尝试它时,我没有收到任何错误,但它只显示“Hello null!”。
索引.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./script.js"></script>
</head>
<body>
  <hello-world name="Joe"></hello-world>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

脚本.js:

class HelloWorld extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: 'open' });

    const p = document.createElement('p');

    p.innerHTML = `Hello ${this.getAttribute('name')}!`;

    this.shadowRoot.append(p);
  }
}

customElements.define('hello-world', HelloWorld);
Run Code Online (Sandbox Code Playgroud)

在任何情况下,我们假设name总是有一个输入。

con*_*exo 5

您不能读取 中的属性 constructor ,否则就违反了规范:

不得检查元素的属性和子元素,因为在非升级情况下不会出现任何属性和子元素,并且依赖升级会降低元素的可用性。
从:https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance

您必须延迟此类工作,直到connectedCallback触发器触发,或者在属性的情况下,配置适当的attributeChangedCallback.

符合规范还将解决您最初的问题,并且将大大增强 Web 组件的功能和实用性。

请注意,选择 HTML 规范中已存在的属性名称作为通用属性也不是最聪明的想法。

class HelloWorld extends HTMLElement {
  p = document.createElement('p');
  constructor() {
    super();
    this.attachShadow({ mode: 'open' }).append(this.p);
  }
  
  static get observedAttributes() { return ['greeting-name']; }
  attributeChangedCallback(attr, oldVal, newVal) {
    if (oldVal === newVal) return; // nothing to do
    switch (attr) {
      case 'greeting-name':
        this.p.textContent = `Hello ${newVal || 'world'}!`;
        break;
    }
  }
  
  connectedCallback() {
    if (!this.getAttribute('greeting-name')) { this.setAttribute('greeting-name', 'world'); }
  }
}

customElements.define('hello-world', HelloWorld);
Run Code Online (Sandbox Code Playgroud)
<hello-world greeting-name="Joe"></hello-world>

<hello-world id="foo"></hello-world>

<input type="text" oninput="document.getElementById('foo').setAttribute('greeting-name', this.value)" placeholder="Type a name" />
Run Code Online (Sandbox Code Playgroud)