În Angular, o componentă este o directivă specială, iar caracteristica sa specială este că are propriul șablon (html) și stil (css). Prin urmare, folosirea componentelor poate face ca codul nostru să fie foarte decuplat, reutilizabil și ușor extensibil. Componentele obișnuite sunt definite astfel:
demo.component.ts:
demo.component.html:
demo.component.scss:
Când facem referire la componentă, conținutul analizat al componentei este redat:
Să presupunem că există nevoie ca componenta să accepte conținut proiectat extern, ceea ce înseamnă că componenta ajunge să prezinte mai mult decât ceea ce definește. În acest moment, protagonistul acestui articol este invitatng-conținut。
Proiecție simplă
Să începem cu cel mai simplu, adăugăm demo.component.html modificat și demo.component.scss la demo.component.html, după cum urmează:
demo.component.html:
demo.component.scss:
Pentru efect, culoarea de fundal a recipientului este definită deliberat ca portocaliu.
În acest moment putem transmite conținut din exterior când facem referire la componentă, iar conținutul extern va fi afișat în zona portocalie:
Proiecție țintită
Dacă sunt mai multe în același timp, cum va fi proiectat conținutul extern?
Să aruncăm o privire la un exemplu mai întâi, pentru distincție, am adăugat o zonă albastră, demo.component.html modificat și demo.component.scss după cum urmează:
demo.component.html:
demo.component.scss:
Pentru a face referire la componentă:
În acest moment, vom vedea că conținutul extern este proiectat în zona albastră:
Desigur, dacă pui prefixul portocaliu după cel albastru, atunci conținutul extern va fi proiectat în zona portocalie:
Așadar, din exemplul de mai sus, putem vedea că dacă există și un simplu , atunci conținutul extern va fi proiectat în ultimul șablon al componentei.
Așadar, cunoscând această problemă, ne-am putea afla dacă putem proiecta conținut extern într-un mod țintit? Răspunsul este, evident, da.
Pentru a face față acestei situații, susțineți unulalegeAtribute care îți permit să proiectezi conținut specific într-un anumit loc. Această proprietate suportă selectori CSS (selector de etichete, selector de clase, selector de atribute、... ) pentru a se potrivi cu ceea ce îți dorești. Dacă niciun atribut select nu este setat pe ng-content, acesta va primi conținutul complet sau conținutul care nu corespunde niciunui alt element ng-content.
Privind direct la exemplu, demo.component.html modificat și demo.component.scss sunt următoarele:
demo.component.html:
demo.component.scss:
După cum se vede din codul de mai sus, zona albastră va primi partea din antetul etichetei, aria roșie va primi partea din div cu clasa "demo2", zona verde va primi partea din div cu numele proprietății "demo3", iar zona portocalie va primi restul conținutului extern (start, I sunt conținutul embed-ului extern, sfârșit).
Pentru a face referire la componentă:
În acest moment, vom vedea conținutul extern proiectat în fișierul specificat .
Extinde cunoștințele
ngProjectAs
Acum știm că proprietatea select a ng-content îți permite să specifici că conținutul extern este proiectat într-un anumit .
Pentru a proiecta corect conținutul bazat pe atributul select, există o limitare – fie că este vorba de un antet de etichetă, un div cu clasa "demo2" sau un div cu un nume de proprietate "demo3", aceste etichete sunt toate subnoduri directe ale etichetei componentă.
Ce s-ar întâmpla dacă nu ar fi un subnod direct? Să modificăm pur și simplu codul care face referire la componenta demo-componentă, să punem antetul etichetei într-un div și să-l modificăm astfel:
În acest moment, vedem că partea cu antetul tab a conținutului nu mai este proiectată în zona albastră, ci în zona portocalie. Motivul este că <ng-content select="header"></ng-content> nu poate corespunde antetului etichetei anterioare, așa că această parte a conținutului este proiectată în zona <ng-content></ng-content> portocalie.
Pentru a rezolva această problemă, trebuie să folosim proprietatea ngProjectAs, care poate fi aplicată oricărui element. Detaliile sunt următoarele:
Prin setarea proprietății ngProjectAs, div-ul unde se află antetul etichetei indică către select="header", iar partea antetului etichetei este proiectată în zona albastră:
<ng-content>Nu "genera" conținut Fă un experiment Pentru a face un experiment, definiți mai întâi o componentă demo-copil-componentă:
componentă demo-componentă pentru:
Apoi, în demo-component cast demo-child-component:
În acest moment, în consolă vedem că inițializarea componentei copil-demo este completă! Aceste cuvinte. Dar când apăsăm butonul pentru a schimba operațiile, inițializarea componentei copil-demo este completă! Nu mai este tipărită, ceea ce înseamnă că componenta noastră demo-copil este instanțiată o singură dată – niciodată distrusă și recreată.
De ce se întâmplă asta?
Cauze ale apariției
<ng-content> Nu "produce" conținut, ci doar proiectează conținut existent. Poți să o consideri echivalentă cu node.appendChild(el) sau metoda $(node).append(el) din jQuery: cu aceste metode, nodul nu este clonat, ci pur și simplu mutat în noua sa locație. Prin urmare, ciclul de viață al conținutului proiectat va fi legat de locul unde este declarat, nu afișat la locul lui.
Aceasta explică și întrebarea anterioară din principiu:Dacă sunt mai multe în același timp, cum va fi proiectat conținutul extern?
Acest comportament se aplică din două motive: consistență și performanță. Ce înseamnă "consistența dorită" că, ca dezvoltator, poți ghici comportamentul aplicației tale pe baza codului ei. Să zicem că am scris următorul cod:
Evident, componenta demo-child-component va fi instanțiată o singură dată, dar acum dacă folosim o componentă dintr-o bibliotecă terță:
Dacă o bibliotecă terță are control asupra ciclului de viață al unei componente copil-de-demo, nu voi avea cum să știu de câte ori a fost instanțiată. Singura modalitate de a face asta este să te uiți la codul bibliotecilor terțe pentru a înțelege logica lor internă de procesare. Semnificația legării ciclului de viață al unei componente de componentele aplicațiilor noastre în loc de wrappers este că dezvoltatorii pot controla că contoarele sunt instanțiate o singură dată, fără a cunoaște codul intern al bibliotecilor terțe.
Motivele performanțeieste mai important. Pentru că ng-content este doar un element în mișcare, poate fi realizat la compilare, nu la rulare, ceea ce reduce semnificativ volumul de lucru al aplicației propriu-zise.
Soluție alternativă
Pentru ca componenta să controleze instanțierea subcomponentelor proiectate, putem face acest lucru în două moduri: folosind <ng-template> elemente și ngTemplateOutlets în jurul conținutului nostru sau folosind directive structurale cu sintaxa "*". Pentru simplitate, vom folosi Syntax în <ng-template> exemplul .
componentă demo-componentă pentru:
Apoi includem demo-child-component în ng-template:
În acest moment, când apăsăm butonul pentru a schimba, consola va imprimaInițializarea componentei demo-copil finalizată!Aceste cuvinte.
|