1

我想要一个从按钮扩展的语义命名自定义元素:比如fab-button

class FabButton extends HTMLButtonElement {
    constructor() {
        super();
        this.html = hyperHTML.bind(this);
    }
}
customElements.define("fab-button", FabButton);

扩展 HTMLButtonElement 似乎不起作用。

有没有办法使用 HyperHTML“document-register-element.js”从非 HTMLElement 扩展?

Codepen 示例: https ://codepen.io/jovdb/pen/qoRare

4

1 回答 1

5

很难回答这个问题,因为很难理解从哪里开始。

TL;DR 解决方案虽然在这里,但需要大量解释。

扩展内置插件是 Web 规范中的鬼魂

不管WHATWG 怎么说,内置插件实际上是一种死亡规范,因为 Webkit 强烈反对它,而 Firefox 以及 Edge,甚至从未发布过自定义元素,也没有推动拥有它们。

因此,作为起点,不鼓励使用自定义元素 V1 规范扩展内置。

不过,您可能对 V0 很幸运,但这只是 Chrome API,它已经是那些为死而生的 API 之一(RIP WebSQL)。

我的 polyfill 按照定义遵循规范

document-register-element polyfill 与 V0 一起诞生,但在 V1 中进行了改进,尽可能地遵循规范,这就是为什么它可以扩展内置插件,因为 WHATWG 仍然包含该部分。

这也意味着您需要了解扩展内置插件的工作原理。

不是通过定义一个简单的类来扩展HTMLButtonElement你得到一个按钮,你至少需要做三件额外的事情:

// define via the whole signature
customElements.define(
  "fab-button",
  FabButton,
  {extends: 'button'}
);

...但也...允许 polyfill 工作

// constructor might receive an instance
// and such instance is the upgraded one
constructor(...args) {
    const self = super(...args);
    self.html = hyperHTML.bind(self);
    return self;
}

重要的是,它在页面上的最基本表示是这样的

<button is="fab-button">+</button>

请记住,使用 ES6 类super(...args)将始终返回当前上下文。它在那里授予超级构造函数没有将其他实例作为升级对象返回。

构造函数不是你的朋友

听起来很刺耳,自定义元素的构造函数只与Shadow DOMand一起工作addEventListener,但实际上并没有。

创建元素时不一定要升级。事实上,它很可能不会升级。

每个浏览器至少有 2 个 bug 和 3 个关于自定义元素初始化的不一致行为,但最好的选择是一旦connectedCallback被调用,你就真的拥有自定义元素节点内容。

connectedCallback() {
  this.slots = [...this.childNodes];
  this.render();
}

通过这种方式,您可以确定您确实在 DOM 上实时渲染了组件,而不是在没有 content 的情况下

我希望我已经以某种方式回答了您的问题,同时警告您如果这是一个新项目的开始,请远离内置的自定义元素:不幸的是,对于您的应用程序的未来,它们不是一个安全的选择。

此致。

于 2018-03-27T21:28:28.657 回答