angular - 在整个非 Angular 应用程序中使用 Angular 2 组件

标签 angular typescript

我有一个现有的、成熟的、非 Angular 网络应用程序的分支。我还有一些来自单独应用程序的现有 Angular 2 组件,我希望重用它们。我想将现有的 Angular 组件散布到各个地方的非 Angular 应用程序中。我想知道这是否可行和可取。请注意,这与 Sprinkling Angular 2 components inside a non-angular page 相似但不完全相同。 .我在下面描述了一个更具体的场景。

目前,我已经想出了如何通过引导一个包装我想要的组件的模块来添加这些 Angular 组件的单个实例。例如。如果我想将 AppComponent 插入到我现有的非 Angular 应用程序中:

app.module.ts 中:

@NgModule({
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts 中:

@Component({
  selector: 'my-app'
  template: '<span>{{value}}</span>'
  ...
})
export class AppComponent { 
   public value: string;
   ...
 }

每当我想要一个 AppComponent 时,我只需附加一个 my-app元素和引导模块如下:

platformBrowserDynamic().bootstrapModule(AppModule);

这工作得非常好,并为 AppComponent 的单个实例提供了我想要的准确结果。但是,我的用例要求我在 DOM 的不同位置有 AppComponent 的两个同时实例。如果我第二次尝试引导 AppModule,核心 Angular 代码会将第二个 AppModule 附加到 my-app元素首先出现在 DOM 中,有效地删除了我的第一个 AppModule 实例。有没有办法告诉 Angular 哪个 my-app要附加到的元素?或者有什么办法解决这个问题?

HTML 示例:

假设我附加了一个 <my-app><body> .然后我的 HTML 看起来像:

<body>
  <my-app>
  </my-app>
</body>

接下来,如果我调用 platformBrowserDynamic().bootstrapModule(AppModule);并设置 value = '111'在 AppComponent 的任何地方,我的 HTML 看起来像:

<body>
  <my-app>
    <span>111</span>
  </my-app>
</body>

然后我添加另一个 my-app选择器添加到 HTML,所以它看起来像:

<body>
  <my-app>
    <span>111</span>
  </my-app>
  <my-app>
  </my-app>
</body>

然后,如果我调用 platformBrowserDynamic().bootstrapModule(AppModule);并设置 value = '222'在新创建的 AppComponent 中,在 AppComponent 逻辑中的任何位置,我的 HTML 如下所示:

<body>
  <my-app>
    <span>222</span>
  </my-app>
  <my-app>
  </my-app>
</body>

当我想要的结果是:

<body>
  <my-app>
    <span>111</span>
  </my-app>
  <my-app>
    <span>222</span>
  </my-app>
</body>

总结:在整个非 Angular 应用程序中使用 Angular 组件是否可行且可取?是否可以同时拥有同一个 Angular 模块的 2 个可见实例?

谢谢!

最佳答案

根据您的场景,我将编写以下代码:

let bootstrapComponentFn: (node: HTMLElement) => void;

platformBrowserDynamic().bootstrapModule(AppModule).then((moduleRef: 

  NgModuleRef<AppModule) => {
    const appRef = moduleRef.injector.get(ApplicationRef);
    const zone: NgZone = moduleRef.injector.get(NgZone);
    const rootComponentFactory = (moduleRef as any).bootstrapFactories[0];  

    bootstrapComponentFn = (node) => {
      zone.run(() => {
        const compRef = rootComponentFactory.create(Injector.NULL, [], node);
       appRef.attachView(compRef.hostView);
      })
    }; 
  });
}

一段时间后

setTimeout(function() {
  let node = document.createElement('my-app');
  document.body.appendChild(node);

  bootstrapComponentFn(node);
}, 2000);

另见 Plunker Example

关于angular - 在整个非 Angular 应用程序中使用 Angular 2 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43355848/

相关文章:

Angular 2 svg - 动态传递高度和宽度

angular - 如果 'some-component-tag' 是一个 Angular 组件并且它有 'some-input-var' 输入,则验证它是否是该模块的一部分

从自己的文件导出接口(interface)时,Angular2 发出警告

angular 5 和 quilljs [Parchment] 无法创建印迹

angular - Angular 6 中的 AuthHttp(从 Angular2 迁移到 Angular6)

css - 在 Angular2 中,如何使 <app-root> 100% 高度

http - 从 URL 下载文件到用户可访问的位置

reactjs - 故事书迁移到 CSF 的 Typescript 问题

javascript - 如何向数组中的项目添加一列?

javascript - Observable<R|T> 中的 <R|T> 在 Angular 中做什么?