Angular 6 - 是否可以在同一页面上使用两个角度元素组件?

时间:2018-05-17 18:49:40

标签: javascript html angular elements angular6

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

  

未捕捉错误:区域已加载。

我使用构建脚本将我的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文件。我理解角度7将使整个过程更容易,但我想知道如何才能实现这一目标。

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

有什么想法吗?

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

4 个答案:

答案 0 :(得分:6)

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

解决方案可以是:

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

答案 1 :(得分:4)

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

Uncaught Error: Zone already loaded.

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

答案 2 :(得分:2)

谷歌的聚合物可能是您正在寻找的而不是角度:

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

Polymer库提供了一组用于创建自定义元素的功能。这些功能旨在使自定义元素更容易,更快速地工作,就像标准DOM元素一样

答案 3 :(得分:1)

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

在您的网站

中,编写组件标记。

您需要创建另一个模块(例如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 {
}

我希望这会对你有所帮助。