Angular 元素:DOMException:无法在“CustomElementRegistry”上执行“define”

Ric*_*rdZ 2 custom-element angular

我使用 Angular Elements 创建了两个自定义元素。

<capp-customtag1> is defined in customtag1.js 
<capp-customtag2> is defined in customtag2.js.

I load <capp-customtag1> with <script type="text/javascript" src="assets/customtag1.js"></script>. 

Similarly, for <capp-customtag2>
Run Code Online (Sandbox Code Playgroud)

分别地,它们按预期工作。但是,如果我尝试在同一个项目(一个 Angular 6 项目)中使用它们,当我尝试加载第二个脚本时,我会收到以下错误:

错误 DOMException:无法在“CustomElementRegistry”上执行“define”:此名称已与此注册表一起使用。

对 CustomElementRegistry 的调用是在 customtag1.js 和 customtag2.js 中进行的。

这是我用来在 Angular Element AppModule 构造函数中创建 capp-customtag1 的代码:

const el = createCustomElement(CustomTag1Component, {injector: this.injector});
customElements.define('capp-customtag1', el);
Run Code Online (Sandbox Code Playgroud)

这是在第二个项目的 AppModule 构造函数中创建 capp-customtag2 的代码:

const el = createCustomElement(CustomTag2Component, {injector: this.injector});
customElements.define('capp-customtag2', el);
Run Code Online (Sandbox Code Playgroud)

为什么两个元素具有相同的自定义元素名称?而且,我该如何解决这个问题。

谢谢你。

skd*_*oid 6

正如所怀疑的那样,这是一个捆绑问题。根本原因是 webpack(驱动 CLI)使用 runtime: webpackJsonpglobal,并且每次加载另一个包(也定义了 webpackJsonp)时都会覆盖它 - 请参阅webpack/webpack#3791(评论)。CLI 没有公开这个选项(这就是为什么 angular 还不支持这个用例)。您可以(尽管我不推荐)手动将webpackJsonp每个包中的全局重命名为唯一的名称。

您还复制了所有polyfills,这可能会导致各种意外结果,因为它们正在填充本机 API 并在不同时间覆盖它们。此外,将所有 angular 包的副本捆绑到每个包中似乎不是最理想的。

目前,如果你想做这种用例,你可能最好的选择是使用 rollup to 之类的东西build UMD bundles,它依赖于 angular 的 UMD 包并从每个元素的包中排除 angular 源。这将需要一些手动工作。

或者,不要使用 CLI 将单个元素构建为二进制文件,将它们视为库并将它们正确地引入构建中,因此您只有一个 webpack 运行时。


dou*_*eya 5

我一直遇到这个错误,并添加了一个检查以确保 customElement 尚未定义。只需在定义元素之前添加以下内容即可修复此错误:

if (!customElements.get('webtest')) {  
    customElements.define('webtest', e3);
}
Run Code Online (Sandbox Code Playgroud)


Har*_*yas 1

我面临类似的问题,我所做的就是在选择器名称之间放置一个连字符。

我的元素选择器名称 webtestweb-test

在app.module.js中

const e3 = createCustomElement(WebelementTestComponent, { injector: this.injector });
customElements.define('webtest', e3);
Run Code Online (Sandbox Code Playgroud)

const e3 = createCustomElement(WebelementTestComponent, { injector: this.injector });
customElements.define('web-test', e3);
Run Code Online (Sandbox Code Playgroud)

那么我的问题就解决了。