typescript - Angular 2: hvordan rendre en dynamisk opprettet komponent etter å ha lagt den til i DOM


For å begynne med, er all koden tilgjengelig i Plunker.

Noe kode

Jeg har en rot Angular2-komponent, slik som dette:

import {Component} from '@angular/core'

@Component({
  selector: 'my-app',
  template: `
    <h2>Angular2 Root Component</h2>
    <div data-dynamic-content></div>
  `,
})
export class App {}

Elementet [data-dynamic-content] er en plassholder for komponenter som jeg vil legge til under kjøring. Disse komponentene er også dynamiske, og opprettes slik:

import {Component} from '@angular/core'

export function createComponent(selector: string, value: string) {
  @Component({
    selector: selector, 
    template: `<h4>Dynamic Component: {{v}}</h4>`,
  })
  class MyDynamicComponent {
    v = value;
  }

  return MyDynamicComponent;
};

Vennligst husk at dette er et ekstremt forenklet eksempel.

Problemstilling

Jeg vil lage forskjellige representasjoner av MyDynamicComponent, legge dem et sted inn i [data-dynamic-content]-elementtreet, og få dem til å være fullt funksjonelle.

Hva jeg har prøvd

Det eneste som har fungert så langt, er å bootstrappe den nyopprettede komponenten når den legges til i DOM:

import {bootstrap} from '@angular/platform-browser-dynamic';
import {createComponent} from './my-dynamic.component';

export function addComponentDynamically(selector, value) {
  var dynamicComponent = createComponent(selector, value);

  var container = document.querySelector('[data-dynamic-content]');
  var wrapper = document.createElement("div");
  wrapper.innerHTML = `<${selector}></${selector}>`;
  container.appendChild(wrapper);

  // !! won't work without this line
  bootstrap(dynamicComponent);
};

Jeg lekte også med DynamicComponentLoader. Det så ikke ut til å passe mine behov - DynamicComponentLoader.loadNextToLocation krever en ViewContainerRef-parameter (f.eks. du må på forhånd vite hvor komponenten din skal plasseres), og det har jeg ikke. Som jeg nevnte tidligere, kunne MyDynamicComponent bli rendret hvor som helst i [data-dynamic-content]-elementtreet, ikke nødvendigvis i dette elementet selv.

Konklusjon

Selv om dette fungerer, tviler jeg sterkt på at en slik tilnærming vil være skalerbar (testet i Chrome med 1000 mer komplekse komponenter - minneforbruket nådde en topp på rundt 750 MB, for deretter å reduseres til ~ 400 MB).

Finnes det en bedre måte å få dette til å fungere på enn å kalle bootstrap om og om igjen?

Relaterte artikler