在单个页面的角度元素中开发了多个自定义元素

时间:2019-01-09 11:05:51

标签: angular custom-element angular-elements

我在不同的Angular元素项目中开发了2个自定义元素,当我尝试在单个html中使用它们时,出现错误“无法在'CustomElementRegistry'上执行'define':此注册表已经使用了该名称” 如何通过此链接开发https://medium.freecodecamp.org/how-to-create-angular-6-custom-elements-web-components-c88814dc6e0a

我知道它与加载两次包装在两个自定义元素中的库有关。该如何解决?

谢谢

3 个答案:

答案 0 :(得分:0)

问题:Elements将整个Angular打包并将其打包为单个JS文件。当其中两个在单个页面上运行时,会发生一些可怕的奇怪冲突,这些冲突可能会或可能不会影响您的元素的行为(很有可能会)。

解决方案:我能够使2个角度元素在单个页面上完美工作的唯一方法是将它们组合到单个应用程序中。它们仍然是单独的元素,这意味着您可以在页面上的任何位置独立地包含那些自定义标签。

您仍然可以按照以下步骤来构建自定义元素,但是在您的app.module.ts文件中,只需添加要定义的其他任何元素:

  ngDoBootstrap() {
    const ele1= createCustomElement(ComponentOne, { injector: this.injector });
    customElements.define('my-ele-one', ele1);

    const ele2= createCustomElement(ComponentTwo, { injector: this.injector });
    customElements.define('my-ele-two', ele2);

    const ele3= createCustomElement(ComponentThree, { injector: this.injector });
    customElements.define('my-ele-three', ele3);

    ....
  }

您的HTML可能类似于

<h1> My Elements </h1>

<my-ele-one></my-ele-one>

<p>What a cool element!</p>

<my-ele-two></my-ele-two>

<div class='turtle'>
 <p><my-ele-three></my-ele-three></p>
</div>

这甚至可以减少您的总体页面开销,因为现在您不会再提取两个完整的应用程序了。

我可能花了50多个小时来尝试配置两个单独的Angular Elements应用程序,使其无法协同工作。我确实需要支持所有浏览器,这绝对是一个很大的因素,因为我可以使某些配置在Chrome或IE上运行,但不能同时在两者上运行。我的元素也不是简单的元素,它们有很多工作部分(引导程序模式,ag-grids等)。希望这对以后的人有所帮助。

答案 1 :(得分:0)

我遇到了同样的问题,但是找到了一个略有不同的解决方案,从而导致代码更少了,尤其是当您有两个以上的自定义元素时。我希望自己写它,但是我将这个解决方案归功于fireship.io的Jeff Delany。

export class AppModule {
  constructor(private injector: Injector) {}

ngDoBootstrap() {
      const elements: any[] = [
        [AwesomeComponent, 'custom-awesome'],
        [CoolComponent, 'custom-cool']
      ];

      for (const [component, name] of elements) {
        const htmlElement = createCustomElement(
          component, {injector: this.injector});
        customElements.define(name, htmlElement);
      }
    }
}

index.html可能看起来像这样:

<h1>Multiple Custom Elements</h1>

<div><custom-awesome></custom-awesome></div>
<div><custom-cool></custom-cool></div>

<p>Hope this helps you out</p>

答案 2 :(得分:0)

我发现了here的另一种方法,它使我可以在另一个角度项目中拥有两个单独的角度腹板组件。我在MacO上做到了

在您的网络组件(这是单独的角度项目my-component)上,运行以下命令

npm install ngx-build-plus -S
ng update ngx-build-plus --force
ng add ngx-build-plus
ng g ngx-build-plus:wc-polyfill
ng g ngx-build-plus:externals

(这将在您的项目目录中创建文件webpack.externals.js),然后在我的package.json的键scripts上添加/编辑键:

"build:my-componente:externals": "ng build --output-hashing none --extra-webpack-config webpack.externals.js --prod --single-bundle true --project my-component && cat dist/my-component/polyfill-webcomp-es5.js dist/my-component/polyfills-es5.js dist/my-component/scripts.js dist/my-component/main-es5.js > dist/myComponent.js"

现在我通过以下方式构建Web组件:

npm run build:my-componente:externals

这将创建文件dist/myComponent.js-以与构建myComponent2.js相同的方式-在您的角度项目中,您可以通过以下两种方式将文件都添加到index.html中:

<head>
...
  <script src="./assets/web-components/myComponent.js" type="text/javascript"></script>
  <script src="./assets/web-components/myComponent2.js" type="text/javascript"></script>
...
</head>

并且两者应该同时工作