In Angular, un componente è una direttiva speciale, e la sua caratteristica speciale è che possiede un proprio template (html) e stile (css). Pertanto, l'uso dei componenti può rendere il nostro codice altamente disaccoppiato, riutilizzabile e facilmente estendibile. Le componenti usuali sono definite come segue:
demo.component.ts:
demo.component.html:
demo.component.scss:
Quando facciamo riferimento al componente, il contenuto analizzato del componente viene reso:
Supponiamo che il componente debba accettare contenuti proiettati esternamente, il che significa che il componente finisce per presentare più di ciò che definisce solo per essa. In questo momento, il protagonista di questo articolo è invitatong-contenuto。
Proiezione semplice
Iniziamo dal più semplice: aggiungiamo il demo.component.html modificato e demo.component.scss a demo.component.html, come segue:
demo.component.html:
demo.component.scss:
Per effetto generale, il colore di sfondo del contenitore è volutamente definito come arancione.
A questo punto possiamo trasmettere contenuti dall'esterno quando facciamo riferimento al componente, e il contenuto esterno sarà visualizzato nell'area arancione:
Proiezione mirata
Se ce ne sono diversi contemporaneamente, come verrà proiettato il contenuto esterno?
Diamo un'occhiata a un esempio, per motivi di distinzione, ho aggiunto un'area blu, il demo.component.html modificato e demo.component.scss come segue:
demo.component.html:
demo.component.scss:
Per fare riferimento al componente:
A questo punto, vedremo che il contenuto esterno viene proiettato nell'area blu:
Ovviamente, se metti il prefisso arancione dopo quello blu, allora il contenuto esterno verrà proiettato nell'area arancione:
Quindi, dall'esempio sopra, possiamo vedere che se esiste anche un semplice , allora il contenuto esterno verrà proiettato nell'ultimo del template del componente.
Quindi, conoscendo questo problema, potremmo chiederci: possiamo proiettare contenuti esterni in modo mirato? La risposta è ovviamente sì.
Per affrontare questa situazione, supporta unoselezionareAttributi che ti permettono di proiettare contenuti specifici in un luogo specifico. Questa proprietà supporta i selettori CSS (selettore di tag, selettore di classe, selettore attributo、... ) per corrispondere a ciò che desideri. Se nessun attributo select è impostato su ng-content, riceverà il contenuto completo, o quello che non corrisponde a nessun altro elemento ng-content.
Guardando direttamente l'esempio, le demo.component.html modificate e demo.component.scss sono le seguenti:
demo.component.html:
demo.component.scss:
Come puoi vedere dal codice sopra, l'area blu riceverà la parte dell'intestazione del tag, l'area rossa riceverà la parte del div con la classe "demo2", l'area verde riceverà la parte del div con il nome di proprietà "demo3" e l'area arancione riceverà il resto del contenuto esterno (start, I sono il contenuto dell'embed esterno, fine).
Per fare riferimento al componente:
A questo punto, vedremo il contenuto esterno proiettato nel file specificato .
Ampliare la conoscenza
ngProjectAs
Ora sappiamo che la proprietà select di ng-content permette di specificare che un contenuto esterno viene proiettato in un dato .
Per proiettare correttamente il contenuto basandosi sull'attributo select, esiste una limitazione: che si tratti di un'intestazione di tag, di un div con una classe "demo2" o di un div con il nome di proprietà "demo3", questi tag sono tutti sottonodi diretti del tag componente.
Cosa succederebbe se non fosse per essere un subnodo diretto? Modifichiamo semplicemente il codice che fa riferimento al componente demo-component, mettiamo l'intestazione del tag in un div e modificiamolo come segue:
A questo punto, vediamo che la parte dell'intestazione a scheda del contenuto non è più proiettata nell'area blu, ma nell'area arancione. Il motivo è che <ng-content select="header"></ng-content> non può corrispondere all'intestazione del tag precedente, quindi questa parte del contenuto viene proiettata nell'area <ng-content></ng-content> arancione.
Per risolvere questo problema, dobbiamo usare la proprietà ngProjectAs, che può essere applicata a qualsiasi elemento. I dettagli sono i seguenti:
Impostando la proprietà ngProjectAs, il div in cui si trova l'intestazione del tag punta a select="header", e la parte dell'header del tag viene proiettata nell'area blu:
<ng-content>Non "generare" contenuti Fai un esperimento Per fare un esperimento, definisci innanzitutto un componente demo-figlio-componente:
Componente demo-component per:
Poi, in demo-component, cast demo-child-component:
A questo punto, nella console vediamo che l'inizializzazione del componente demo-child-component è completa! Queste parole. Ma quando clicchiamo sul pulsante per cambiare operazione, l'inizializzazione del demo-child-component è completa! Non viene più stampato, il che significa che il nostro componente demo-child-component viene istanziato solo una volta - mai distrutto e ricreato.
Perché sta succedendo questo?
Cause di verifica
<ng-content> Non "produce" contenuti, si limita a proiettare contenuti esistenti. Puoi considerarlo equivalente a node.appendChild(el) o al metodo $(node).append(el) in jQuery: con questi metodi, il nodo non viene clonato, ma semplicemente spostato nella sua nuova posizione. Pertanto, il ciclo di vita del contenuto proiettato sarà vincolato al luogo in cui viene dichiarato, non visualizzato sul posto.
Questo spiega anche la domanda precedente tratto dal principio:Se ce ne sono diversi contemporaneamente, come verrà proiettato il contenuto esterno?
Questo comportamento avviene per due motivi: coerenza e prestazioni. Cosa significa "coerenza desiderata" che, come sviluppatore, puoi intuire il comportamento della tua applicazione in base al suo codice. Supponiamo che abbia scritto il seguente codice:
Ovviamente il componente demo-child-component verrà istanziato una sola volta, ma ora se usiamo un componente di una libreria di terze parti:
Se una libreria di terze parti ha il controllo sul ciclo di vita di un componente demo-child, non avrò modo di sapere quante volte è stato istanziato. L'unico modo per farlo è guardare il codice delle librerie di terze parti per comprendere la loro logica interna di elaborazione. Il significato di legare il ciclo di vita di un componente ai nostri componenti applicativi invece che agli involucri è che gli sviluppatori possono controllare che i contatori vengano istanziati solo una volta, senza conoscere il codice interno delle librerie di terze parti.
Motivi delle prestazioniè più importante. Poiché ng-content è solo un elemento in movimento, può essere fatto a tempo di compilazione, non a runtime, il che riduce notevolmente il carico di lavoro dell'applicazione effettiva.
Soluzione alternativa
Affinché il componente possa controllare l'istanziazione dei sottocomponenti proiettati, possiamo farlo in due modi: usando <ng-template> elementi e ngTemplateOutlets attorno al nostro contenuto, oppure usando direttive di struttura con sintassi "*". Per semplicità, useremo Syntax nell'esempio <ng-template> .
Componente demo-component per:
Poi includiamo demo-child-component nel ng-template:
A questo punto, quando premiamo il pulsante per cambiare, la console stamperàInizializzazione del componente demo-child-terminata!Queste parole.
|