【问题标题】:Custom Elements Illegal Constructor in FireFoxFireFox 中的自定义元素非法构造函数
【发布时间】:2017-04-04 19:30:18
【问题描述】:

我有一个带有以下构造函数的 CustomElement:

export default class SomeCustomElement extends HTMLElement {
    constructor(templateId) {
        super();
        this.insertTemplateInstance(templateId);
    }
    ...
}

我可以毫无问题地在 Chrome 中注册该元素。

但是使用 Firefox 和 webcomponents-loader.jshttps://github.com/webcomponents/webcomponentsjs 加载的 polyfill 我在调用 super() 时收到错误消息 TypeError: Illegal constructor

有人知道这是什么原因吗?

更多背景:

自定义元素的注册过程如下:

window.addEventListener("WebComponentsReady", function () {
    customElements.define(elementName, SomeCustomElement);
});

【问题讨论】:

  • 没有。但我使用汇总能够使用 es2015 模块/导入
  • 您应该尝试使用 webcomponents-lite。这里的错误表明当元素实例化时 polyfill 尚未加载。此外,您不应在 WebComponentsReady 回调中调用 customElement.define。
  • 那么我应该在哪里调用定义?我认为在 WebComponentsReady 中调用它可以确保在完全加载 polyfill 后调用它
  • 在加载了 polyfill 之后,或者在导入的文件中(使用 )。 WebComponentReady 确保组件已被定义和实例化,以便调用其方法。
  • polyfill 应该同步加载。我已经用 webcomponents-lite 对其进行了测试,它在 firefox 上运行良好。无需活动。只需将

标签: javascript ecmascript-6 web-component polyfills custom-element


【解决方案1】:

如果您不想出现这种错误,请使用webcomponents-lite.js 而不是webcomponent-loader.js,这是由于如果您使用webcomponents-loader.js,polyfill 将异步加载。

以下示例适用于 Firefox(以及所有现代浏览器):

class SomeCustomElement extends HTMLElement
{
  constructor()
  {
    console.log( 'created' )
    super()
  }

  connectedCallback() {
    console.log( 'connected' )
    this.innerHTML = "Hello"
  }
}

customElements.define( 'c-e', SomeCustomElement ) 
<script src=https://rawgit.com/webcomponents/webcomponentsjs/master/webcomponents-lite.js></script>

<c-e></c-e>

但是,如果您仍想使用 webcomponents-loader.js,则必须将自定义元素定义插入到外部文件中,并使用 HTML 导入加载它:

<link rel="import" href="my-element.html">

【讨论】:

  • 2017 年 11 月在 Linux 上的 FF 56、57 中不起作用。由于尝试将 HTMLElement 作为构造函数直接调用,因此引发了对 super 的调用。
  • 您在about:config 中设置了标志吗?还有什么操作系统?除了 linux 还没试过。
  • @JaredSmith 不应该取消设置,它不符合自定义元素 v1。仅使用 polyfill。
  • 我也没有设置它,仍然得到 polyfill 文件的错误。仍然随叫随到超级。刚刚在 OSX High Sierra 上测试了 FF 54,同样的问题。
  • 没关系,通过阅读原始问题的 cmets 发现问题。在 polyfill 之前有文件并尝试在 WebComponentsReady 监听器中注册。他们确实需要更好的文档来解决所有这些问题(尽管我意识到很难为正在积极开发的东西保持更新)。
【解决方案2】:

提前警告:我不是 html 导入的忠实粉丝。我偶然发现了这个试图让 ES 6 基于类的自定义元素在 Firefox 中工作。对于基于接受的答案的条件-polyfill-loading-no-html-import 解决方案,请继续阅读...

有条件地加载 polyfill 有点棘手。根据@Supersharp 的回答/cmets,由于某种原因,polyfill 必须 同步加载(尽管官方文档中没有提到这一点)。所以现在你有两个不吸引人的选择:无条件地包含它以获得必要的同步加载或......使用document.write

<script>
;(function() {
  var str = '';
  // You could make this more fine-grained if desired by doing
  // more feature detection and loading the minimal polyfill file 
  if (!window.customElements) str += '<script src="./node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>';
  str += '<script src="./elements.js"></script>';
  document.write(str);
})();
</script>
<foo-bar></foo-bar>

然后在elements.js:

class FooBar extends HTMLElement {
  constructor () {
    console.log("constructing");
    super();
  }

  connectedCallback () {
    console.log("connecting");
  }

  disconnectedCallback () {
    console.log("disconnecting");
  }
};
// Note that because of the synchronous loading we don't
// need to listen for the event
customElements.define('foo-bar', FooBar);

document.write 被广泛不喜欢是有充分理由的,但恕我直言,这是一个合法的用例。请注意,这里的大多数反对意见(没有预取等)都可以通过使用服务工作者(对于支持它们的浏览器)来改善。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 2021-10-04
    • 2023-03-18
    • 2013-04-05
    • 2020-04-17
    • 2017-03-22
    • 1970-01-01
    相关资源
    最近更新 更多