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

qhhrdooz  于 2023-03-21  发布在  Angular
关注(0)|答案(4)|浏览(172)

我尝试托管独立的Angular 元素,我可以把它放到一个非Angular 的网页。它的工作很好,当我只有一个..但当我加载两个或多个在同一个页面上,我得到这个错误:
未捕获的错误:区域已加载。
我使用构建脚本将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文件 Package 在一个自执行函数中,以尝试限制范围。不幸的是,没有修复任何问题。
有什么想法吗?
人们似乎对什么是角元素感到困惑。为了澄清你可以看这个视频https://www.youtube.com/watch?v=4u9_kdkvTsc。最后几分钟特别显示了一个角元素被导出并包含在一个非角页面上。我试图在同一页面上包含多个元素。

j1dl9f46

j1dl9f461#

基于前面的讨论,我的想法如下:因为你用元素创建的每个bundle都是在zone.js中加载的,所以你会收到错误消息:

Uncaught Error: Zone already loaded.

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

ifmq2ha2

ifmq2ha22#

我认为你不应该在一个网站上使用2角。
解决方案可以是:

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

编辑:
自从我的原版发布以来,就出现了一种技术。使用Microfrontends(MFE)你可以在同一个页面上添加更多的应用程序。在Angular中,它将主要成为一个新的路由器元素。任何ESM import()可以用于延迟加载的地方,而Angular默认只在路由器中支持它。

jtjikinw

jtjikinw3#

谷歌的聚合物可能是你正在寻找的,而不是角:
https://www.polymer-project.org/
Polymer库提供了一组用于创建定制元素的特性,这些特性旨在使创建像标准DOM元素一样工作的定制元素变得更容易、更快

mlmc2os5

mlmc2os54#

这是一个完美的解决方案,工作在Angular 5+.对于Angular 6我没有这样做.我已经这样做了一个巨大的CMS项目,我插入组件在几个页面,甚至2相同的Angular 模块在一个页面.你可以使用一个Angular 项目.
在您站点中,编写组件标记。
您需要创建另一个模块(例如mainHelper)来导出每个选定的Angular 标记。

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。
你的第一个模块应该是这样的

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 {
}

希望这对你有帮助。

相关问题