为什么 `is` 属性只适用于覆盖内置元素的 Web 组件?

Why does the `is` attribute only work on web components that override a built-in element?

is="" 属性是一种通过自定义元素为内置元素提供额外智能的方法,但它似乎仅在您的自定义元素的 JS 实现扩展了您正在使用的内置元素时才有效使用它。

在我看来,将附加功能定义为自定义元素然后将其应用于 任何 内置元素会非常有用。这将允许 Web 组件的用户从增强的行为中受益,同时保留标准语义元素的含义。

此限制的原因是什么?

Firefox 确实允许对内置元素进行 is="" 升级(https://codepen.io/bdhowe/pen/QRLrWQ?editors=1010), but other browsers I've tried do not, and the MDN 文档说它只能在自定义元素 "extends the element type it is being applied to".

class MyElement extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow({mode: 'open'});
    const span = document.createElement('span');
    span.textContent = "Hello, world!";
    shadow.appendChild(span);
  }
}

customElements.define('my-elem', MyElement);
/* I want this to render "Hello, world!" twice. */
<div is="my-elem"></div>
<my-elem></my-elem>

参考:

有两种使用自定义元素定义的方法,您观察的是两者的区别。


如果您想将自定义元素用作自己的元素,例如

<my-elem></my-elem>

那么你需要使用extends HTMLElement。对于您的示例,这就是目前 "Hello, World!" 的结果。


如果您希望自定义元素与 is="" 一起使用,例如

<div is="my-elem"></div>

那么你需要使用extends HTMLDivElement以及在定义中指定customElements.define('my-elem', MyElement, {extends: 'div'});


这是两种不同的使用方法,不要混用。我会假设他们不能混合的原因是因为同时工作需要多重继承并且不受支持。

尽管可能会很不雅观,但还是可以将一些东西拼凑在一起。最佳做法是使用其中之一。

您可以通过扩展自定义元素的定义来覆盖(不是 built-in)自定义元素 class。

class Base extends HTMLElement {}
customElements.define( 'base-element', Base )

class BaseExtension extends Base {}
customElements.define( 'extended-element', BaseExtension )