V Angularu je komponenta speciální direktiva a její speciální vlastností je, že má vlastní šablonu (html) a styl (css). Proto použití komponent může náš kód učinit vysoce odděleným, znovupoužitelným a snadno rozšiřitelným. Obvyklé složky jsou definovány následovně:
demo.component.ts:
demo.component.html:
demo.component.scss:
Když odkazujeme na komponentu, vykreslí se její analyzovaný obsah:
Předpokládejme, že komponenta musí přijímat externě promítaný obsah, což znamená, že komponenta nakonec prezentuje více než jen to, co definuje. V tuto chvíli je hlavní postava tohoto článku pozvánang-obsah。
Jednoduchá projekce
Začněme nejjednodušším, přidejte upravený demo.component.html a demo.component.scss do demo.component.html, a to následovně:
demo.component.html:
demo.component.scss:
Pro efekt je barva pozadí kontejneru záměrně definována jako oranžová.
V tomto bodě můžeme při odkazování na komponentu předávat obsah zvenčí a externí obsah se zobrazí v oranžové oblasti:
Cílená projekce
Pokud jich je najednou více, jak bude externí obsah promítán?
Podívejme se nejprve na příklad, pro rozlišení jsem přidal modrou oblast, upravený demo.component.html a demo.component.scss následovně:
demo.component.html:
demo.component.scss:
Pro odkaz na komponentu:
V tomto bodě uvidíme, že externí obsah je promítán do modré oblasti:
Samozřejmě, pokud za modrou dáte oranžovou předvolbu, pak se externí obsah promítne do oranžové oblasti:
Z výše uvedeného příkladu vidíme, že pokud existuje také jednoduché , pak se externí obsah promítne do poslední šablony komponenty.
Takže s vědomím tohoto problému se můžeme ptát, zda můžeme externí obsah promítat cíleně? Odpověď je samozřejmě ano.
Abyste to zvládli, podpořte jednohovybratAtributy, které umožňují promítat konkrétní obsah na konkrétní místo. Tato vlastnost podporuje CSS selektory (výběr tagů, výběr tříd, výběr atributů、... ) aby odpovídaly tomu, co chcete. Pokud na ng-content není nastaven žádný atribut select, obdrží celý obsah nebo obsah, který neodpovídá žádnému jinému ng-obsahovému prvku.
Přímo na příklad jsou upravené demo.component.html a demo.component.scss následující:
demo.component.html:
demo.component.scss:
Jak můžete vidět z výše uvedeného kódu, modrá oblast obdrží část tag headeru, červená oblast část divu s třídou "demo2", zelená oblast část divu s názvem vlastnosti "demo3" a oranžová oblast zbytek externího obsahu (začátek, I jsem obsah externího embed, end).
Pro odkaz na komponentu:
V tomto bodě uvidíme externí obsah promítnutý do specifikované .
Rozšiřování znalostí
ngProjectAs
Nyní víme, že vlastnost select ng-content umožňuje specifikovat, že externí obsah je promítán do dané .
Pro správné promítání obsahu na základě atributu select existuje omezení – ať už jde o hlavičku tagu, div s třídou "demo2" nebo div s vlastnostním názvem "demo3", všechny tyto tagy jsou přímými poduzly tagu komponenty.
Co by se stalo, kdyby to nebyl přímý subuzel? Jednoduše upravme kód, který odkazuje na demo-komponentu, vložíme hlavičku tagu do divu a upravíme ji následovně:
V tomto bodě vidíme, že záhlaví záložky už není promítáno do modré oblasti, ale do oranžové oblasti. Důvodem je, že <ng-content select="header"></ng-content> nemůže odpovídat předchozí hlavičce tagu, takže tato část obsahu je promítnuta do <ng-content></ng-content> oranžové oblasti.
K vyřešení tohoto problému musíme použít vlastnost ngProjectAs, kterou lze aplikovat na jakýkoli prvek. Podrobnosti jsou následující:
Nastavením vlastnosti ngProjectAs ukazuje div, kde se nachází hlavička tagu, na select="header" a část hlavičky tagu je promítnuta do modré oblasti:
<ng-content>Nevytvářejte "generujte" obsah Udělejte experiment Pro provedení experimentu nejprve definujte komponentu demo-potomka:
Demo-komponenta k:
Pak v demo-komponentě cast-demo-dítě:
V tomto bodě v konzoli vidíme, že inicializace demo-child-komponenty je dokončena! Tato slova. Ale když klikneme na tlačítko pro přepnutí operací, inicializace demo-potomka komponenty je dokončena! Už se netiskne, což znamená, že naše demo-child komponenta je instancována pouze jednou – nikdy není zničena a znovu vytvořena.
Proč se to děje?
Příčiny výskytu
<ng-content> Nevytváří "produkce" obsahu, jen promítá existující obsah. Můžete si to představit jako ekvivalent metody node.appendChild(el) nebo metody $(node).append(el) v jQuery: u těchto metod se uzel neklonuje, pouze se přesune na nové místo. Životní cyklus promítaného obsahu bude tedy vázán na místo, kde je deklarován, nikoli zobrazen přímo na místě.
To také vysvětluje předchozí otázku z principu:Pokud jich je najednou více, jak bude externí obsah promítán?
Toto chování je prováděno ze dvou důvodů: konzistence a výkonu. Co znamená "požadovaná konzistence", že jako vývojář můžete odhadnout chování své aplikace podle jejího kódu. Řekněme, že jsem napsal následující kód:
Samozřejmě komponenta demo-child-component bude instancována jednou, ale nyní, pokud použijeme komponentu z knihovny třetí strany:
Pokud má knihovna třetí strany kontrolu nad životním cyklem komponenty demo-child komponenty, nebudu mít způsob, jak zjistit, kolikrát byla instancována. Jediný způsob, jak toho dosáhnout, je podívat se do kódu knihoven třetích stran, abyste pochopili jejich interní logiku zpracování. Význam vázání životního cyklu komponenty na naše aplikační komponenty místo obalů spočívá v tom, že vývojáři mohou ovládat, že čítače jsou instancovány pouze jednou, aniž by znali interní kód knihoven třetích stran.
Důvody výkonuje důležitější. Protože ng-content je pouze pohyblivý prvek, lze jej provádět při kompilaci, nikoli za běhu, což výrazně snižuje zátěž samotné aplikace.
Řešení
Aby komponenta mohla řídit instanci promítaných podkomponent, můžeme to udělat dvěma způsoby: použitím <ng-template> prvků a ngTemplateOutlets kolem našeho obsahu, nebo použitím strukturálních direktiv se syntaxí "*". Pro jednoduchost použijeme syntaxi v příkladu <ng-template> .
Demo-komponenta k:
Pak zahrnujeme demo-child-komponentu do ng-template:
V tuto chvíli, když klikneme na tlačítko pro přepnutí, konzole vytiskneInicializace demo-child-komponent dokončena!Tato slova.
|