使用webcomponent增强/扩展原生元素

289 阅读2分钟

前言

自定义元素允许使用扩展原生内置元素,支持增强已经存在的HTML元素,例如 imgbutton

扩展现有HTML元素的好处是继承了元素的所有属性和方法。这允许对现有元素进行逐步的增强。这意味着即使在不支持自定义元素的浏览器中,它仍是可用的。它只会降级到默认的内置行为。而如果它是一个全新的HTML标签,那它将会完全无法使用。

例如:我们想要增强一个HTML<button>标签

class MyButton extends HTMLButtonElement {
  constructor() {
    super();
    // do something
  }
 
  connectedCallback() {
    // do something
  }
 
  someMethod() {
    // do something
  }
}
customElements.define('my-button', MyButton, {extends: 'button'});

我们的 web component 不在继承更通用的 HTMLElement,而是继承 HTMLButtonElement。这时我们使用customElements.define() 的时候还需要添加一个额外的参数 {extends: 'button'} 来表示我们的类扩展的是<button> 元素。这可能看起来有些多余,因为我们已经表明了我们想要扩展的是 HTMLElementButton,但是这是必要的,因为一些元素共享一个DOM接口。例如 <q> 和 <blockquote>都继承HTMLQuoteElement接口。

这个增强后的 button 可以通过 is 属性来被使用。

<button is="my-button">

现在它将被我们的MyElement类增加,如果它加载在一个不支持自定义元素的浏览器中,它将降级到一个标准的按钮,真正的渐进式增强。

注意,在扩展现有元素时,不能使用Shadow DOM。这只是一种扩展原生HTML元素的方法,它继承了所有现有的属性、方法和事件,并提供了额外的功能。当然可以在组件中修改元素的DOM和CSS,但是尝试创建一个Shadow root将会抛出一个错误。

扩展内置元素的另一个好处就是,这些元素也可以应用于子元素被限制的情况。例如thead元素只允许tr作为其子元素,因此元素将呈现无效标记。这种情况下,我们可以拓展内置的tr元素。并像这样使用它:

<table>
  <thead>
    <tr is="my-tr"></tr>
  </thead>
</table>

这种创建web components的方式带来了更多可能,使得真正的渐进式增强成为可能。虽然vue也是渐进式增强框架,但毕竟还是要引入一个外部框架,期待webcomponent规范的更加完善和更多的浏览器支持。