【问题标题】:Multiple Custom element developed in angular element in single page单个页面中以角度元素开发的多个自定义元素
【发布时间】:2019-06-04 03:27:29
【问题描述】:

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

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

谢谢

【问题讨论】:

    标签: angular custom-element angular-elements


    【解决方案1】:

    我发现here 替代方式允许我在另一个角度项目中拥有两个单独的角度网络组件。我是在 MacOs 上做的

    在您的网络组件(这是单独的 Angular 项目 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 的方式相同 - 在您的 Angular 项目中,您可以将两者都添加到您的 index.html by

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

    两者应该同时工作

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,但发现了一个稍微不同的解决方案,它可以减少代码,特别是如果您有 2 个以上的自定义元素。我希望我能写出来,但我感谢 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>
      

      【讨论】:

      • 我正在使用 angular 11,这个解决方案也对我有用。将 Web 组件注册到 ngDoBootstrap 方法已成功在同一页面中显示我的所有 Web 组件。
      【解决方案3】:

      问题: 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 中运行,但不能同时在两者中运行。我的元素也不是简单的元素,它们有很多工作部分(bootstrap modals、ag-grids 等)。希望这对将来的某人有所帮助。

      【讨论】:

      • 是的,这就是我所做的。谢谢。由于您正在研究角度元素,因此向您提出了另一个问题。你用过viewEncapsulation.shadowDom吗?当我使用它时,样式不会被应用。角度有问题github.com/angular/angular/issues/26853
      • 我们关闭了封装 (viewEncapsulation.none),因为我们也遇到了问题。我们在一些非常古老的地方加入了这个,我们的样式并没有真正影响页面,所以这对我们来说没什么大不了的。希望你能明白。
      猜你喜欢
      • 2022-01-22
      • 1970-01-01
      • 2019-12-10
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 2023-01-30
      • 2019-12-11
      • 1970-01-01
      相关资源
      最近更新 更多