首页 文章

在非Angular应用程序中使用Angular 2组件

提问于
浏览
4

我有一个预先存在的,成熟的,非Angular Web应用程序的分支 . 我还有一些我希望重用的独立应用程序中现有的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附加到DOM中首先出现的 my-app 元素,从而有效地删除我的第一个AppModule实例 . 有没有办法告诉Angular要追加哪个 my-app 元素?或者有什么方法可以解决这个问题?

HTML Example

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

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

接下来,如果我在AppComponent中的任何地方调用 platformBrowserDynamic().bootstrapModule(AppModule); 并设置 value = '111' ,我的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>

然后,如果我在AppComponent逻辑中的任何地方调用 platformBrowserDynamic().bootstrapModule(AppModule); 并在新创建的AppComponenet中设置 value = '222' ,我的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>

In summary: 在非Angular应用程序中使用Angular组件是否可行且明智?是否可以同时拥有同一个角度模块的2个可见实例?

谢谢!

1 回答

  • 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

相关问题