簡體   English   中英

如何在 Angular 中使用第三方庫動態創建組件?

[英]How do I dynamically create components with third party library in Angular?

使用 Angular 10

SO上有很多與此類似的問題,但我還沒有找到一個可以回答我的情況的問題。

我希望有人可以指導我。

我正在使用第三方庫來顯示 360° 照片。 這個第三方庫有一個內置的 API 來顯示場景中的熱點。 只需為庫提供您想要成為熱點的元素,它就會處理 rest。

我的大部分工作都按預期工作,但有幾件沒有。

到目前為止,我正在動態生成我的組件,如下所示:

this._hotspotFactory = this.resolver.resolveComponentFactory(HotspotComponent);
const component = this._hotspotFactory.create(this.injector);

//Hydrate component with  bunch of data
component.instance.id = data.id;
...

// Create the Hotspot with Third Party
// Calling this third party method injects the native element into the DOM. 
// Passing the nativeElement in. Looks great at first glance. 
const hotspot = this._scene.createHotspot(data, component.location.nativeElement);

this.appRef.attachView(component.hostView);
component.hostView.detectChanges();

if(component.instance.over.observers.length) {
  hotspot.on('over', (evt) => {
    this.zone.run(() => {
      component.instance.over.emit(evt);
    });
  });
}

if(component.instance.out.observers.length) {
  hotspot.on('out', (evt) => {
    this.zone.run(() => {
      component.instance.out.emit(evt);
    });
  });
}

if(component.instance.navigate.observers.length) {
  hotspot.on('click', (evt) => {
    this.zone.run(() => {
      component.instance.navigate.emit(evt);
    })
  });
}

沒有拋出任何錯誤,我成功地看到了熱點應該在場景中的位置。 甚至HotspotComponent模板中的數據插值也會按預期發生。

但是, [ngStyle]綁定永遠不會導致HotspotComponent中的動態樣式。

我 99% 確定這是因為組件中沒有進行更改檢測。

我使用this.appRef.attachView(component.hostView)手動附加視圖,因為第三方負責將元素注入 DOM,而不是 Angular。 因此 Angular 需要了解它,以便執行更改檢測。

即使手動調用attachView ,我仍然認為 Angular 不知道視圖中的這個組件,因為 Angular Chrome 擴展調試器沒有在其開發工具中將其注冊為視圖中的已知組件......盡管看到它在屏幕上和 DOM 中。

我錯過了什么?

組件有什么變化檢測策略? 當一個組件被添加到視圖中時,它的生命周期鈎子將由 angular( ngOninitngAfterContentInit等) 觸發。 在這些中記錄一些內容,看看是否正在調用主題生命周期鈎子。 無論更改檢測策略如何,在組件添加到視圖后,都應在組件上進行一個更改檢測周期。

如果生命周期鈎子調用沒有發生,那么這意味着 angular 沒有參與將元素添加到 DOM。

似乎 angular 有一個生命周期掛鈎,正好適合您的用例'ngDoBootstrap'

由於我們無法調試您的完整源代碼,從您提到的信息看來,您嘗試附加到視圖的動態組件似乎不適用於 NgModule 中的 Angular。 angular 引導的每個組件都必須在 NgModule 中

您可以使用'ngDoBootstrap'動態引導它。

它以下列方式使用:

ngDoBootstrap(appRef: ApplicationRef) {

      this.fetchDataFromApi().then((componentName: string) => {
        if (componentName === 'ComponentOne') {
          appRef.bootstrap(ComponentOne);
        } else {
          appRef.bootstrap(ComponentTwo);
        }
      });
    }

在您的情況下,您可以在將組件附加到視圖之前執行此操作。

...
appRef.bootstrap(component);
this.appRef.attachView(component.hostView);
component.hostView.detectChanges();
...

請在此處查看文檔: https://angular.io/api/core/ApplicationRef

同樣的問題,即使我也在幾天前被卡住了。 這是我完整討論的地方。 您將獲得您正在尋找的完整答案StackOverflow 討論

Stackblitz 鏈接在這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM