【问题标题】:Angular 6 - Is it possible to use two angular element components on the same page?Angular 6 - 是否可以在同一页面上使用两个 Angular 元素组件?
【发布时间】:2018-06-07 02:22:57
【问题描述】:

我正在尝试托管可以放入非角度网页的独立角度元素。当我只有一个时,它工作得很好.. 但是当我在同一页面上加载两个或更多时,我收到此错误:

未捕获的错误:区域已加载。

我正在使用构建脚本将我的 dist 文件连接到一个 js 文件中......然后将其放入我的项目中

const fs = require('fs-extra')
const concat = require('concat')


const files = [
    './dist/elementsApp/runtime.js',
    './dist/elementsApp/polyfills.js',
    './dist/elementsApp/scripts.js',
    './dist/elementsApp/main.js',
]


fs.ensureDir('elements')
.then(() => {
  console.log('success!')
  concat(files, 'elements/include-me-somewhere-else.js')
})
.catch(err => {
  console.error(err)
})

我只能在一页上拥有这些 js 文件之一。我知道 Angular 7 将使整个过程变得更容易,但我想知道我现在如何才能做到这一点。

我还尝试将导出的 js 文件包装在一个自执行函数中以尝试限制范围。不幸的是,它没有解决任何问题。

有什么想法吗?

人们似乎对角元素是什么感到困惑。如需澄清,您可以观看此视频https://www.youtube.com/watch?v=4u9_kdkvTsc。最后几分钟特别显示了一个角度元素被导出并包含在一个非角度页面上。我正在尝试在同一页面上包含多个元素。

【问题讨论】:

  • 您在一个站点上使用 2 个 Angular 应用程序的目的是什么?
  • 可能值得在 Angular 的 Gitter 频道上提问。构建 Angular 元素的人有时会在那里闲逛。
  • 您是否正在这样做,以便您想要的每个组件都作为它自己的模块存在?
  • @MichaelSolati 是的,我是
  • @hamobi 我相信那是你的问题。每次导入都会带来 int zone.js 并且您会遇到问题。您应该查看一个模块,该模块可以导入您想要的元素并从那里开始。 (我可以拼凑一个快速的 repo tp 使这个过程更容易。无论如何我都需要这样做)。

标签: javascript html angular elements angular6


【解决方案1】:

我认为你不应该在一个网站上使用 2 angular。

解决方案可以是:

  • 在 Angular 中构建整个站点。代码的其他部分可以添加到应用程序中。
  • 使用子模块并将两个应用程序与父路由器合并。
  • 为每个 Angular 组件使用 iframe。这样 ngzone 就不会发生冲突了。

【讨论】:

  • 这是两个 angular-elementa 组件。它们旨在用作角度上下文之外的小部件。它们是 Angular 6 的新功能。它们不是传统意义上的 Angular 应用程序。
  • 我通过不使用区域来开始工作。 blog.angularindepth.com/…
  • 从 Angular 13 开始,您可以使用微前端架构。使用它,您可以将两个应用程序添加到同一个页面并让它加载一些路由。
【解决方案2】:

以下是我基于之前讨论的想法。因为您使用元素创建的每个包都加载到 zone.js 中,所以您会收到错误消息:

Uncaught Error: Zone already loaded.

您可以并且应该考虑的是不要将'./dist/elementsApp/polyfills.js' 连接到您的捆绑包中(对于您捆绑生成的每个元素)。而是使用 polyfill.js 文件作为单独导入到您的 HTML 中,并在您要导入的任何和所有元素包之前导入它。

【讨论】:

  • 我会试一试,然后告诉你结果
  • 抱歉耽搁了......我尝试这样做并得到错误“错误:在此配置中 Angular 需要 Zone.js” 我确保在我的其他包含之前包含 polyfills.js跨度>
  • 不起作用,这与加载 polyfill 的次数无关,而是在加载两个 Angular 元素时,Zone 本身被构建了两次
【解决方案3】:

Google 的 Polymer 可能是您正在寻找的,而不是 angular:

https://www.polymer-project.org/

Polymer 库提供了一组用于创建自定义元素的功能。这些功能旨在让自定义元素像标准 DOM 元素一样工作更轻松、更快速

【讨论】:

  • 感谢您的建议,但我的团队已经对此进行了探索。不完全是我们正在寻找的。我需要一个纯角度解决方案来包含多个角度元素。
【解决方案4】:

这是一个在 angular 5+ 上完美运行的解决方案。对于角度 6,我没有这样做。 我已经为一个巨大的 CMS 项目做了这个,我在几页中插入了组件,甚至在一页中插入了 2 个相同的角度模块。您可以使用一个 Angular 项目。

在您的站点中,编写组件标签。

您需要创建另一个模块(例如 mainHelper)来导出每个选定的角度标签。

import {NgModule, ApplicationRef, ComponentFactoryResolver} from '@angular/core';
import {FirstModule} from 'YOUR MODULE PATH';
import {FirstComponent} from 'YOU COMPONENT PATH';
import {SecondModule} from 'YOUR MODULE PATH';
import {SecondComponent} from 'YOU COMPONENT PATH';


@NgModule({
  imports: [
    FirstModule,
    SecondModule
  ],
})

export class MainHelper {
  constructor(private resolver: ComponentFactoryResolver) {
  }
  components = [
FirstComponent,
SecondComponent
  ];


  ngDoBootstrap(ref: ApplicationRef) {
    this.components.forEach((component) => {
      const factory = this.resolver.resolveComponentFactory(component);
      const elements = document.getElementsByTagName(factory.selector); //get angular tags on your main website
      if (elements.length > 0) {
        if (elements.length > 1) {
          const selector = factory.selector;
          for (let i = 0; i < elements.length; i++) {
            elements[i].id = selector + '-' + i;
            (<any>factory).factory.selector = '#' + elements[i].id;
            ref.bootstrap((<any>factory).factory);
            // elements[i].id = '';
          }
          (<any>factory).factory.selector = selector;
        } else {
          ref.bootstrap(component);
        }
      }
    });
  }
}

在您的 main.ts 中,您可以导入 MainHelper 模块并引导 MainHelper。

你的 FirstModule 会是这样的:

import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {BrowserModule} from '@angular/platform-browser'; 
import {FirstComponent} from './first.component';
import {AnotherComponent} from './another/another.component';
@NgModule({
  imports: [
    CommonModule,
    BrowserModule,
  ],
  providers: [
    SampleService // you need provide your services for all the modules
  ],
  declarations: [
    FirstComponent,
    AnotherComponent,
  ],
  bootstrap: [FirstComponent] // important
})
export class ECommerceModule {
}

希望对你有帮助。

【讨论】:

  • 请观看此视频:youtube.com/watch?v=4u9_kdkvTsc 观看结尾,他将 angular 元素导出为连接的 javascript 文件并将其添加到外部网站。我正在尝试在同一页面上包含其中两个文件。
  • 我明白了。这个周末我会做一个检查,但是,我还是更喜欢手动做。我认为,解决方案是,当你想引导 angularElements 时,你需要对其中的一个进行引导。我会调查的。
猜你喜欢
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
  • 1970-01-01
  • 2017-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多