Qual è la differenza tra @ViewChild e @ContentChild?


189

Angolare 2 fornisce @ViewChild, @ViewChildren, @ContentChilde @ContentChildrendecoratori per l'interrogazione di elementi discendenti di un componente.

Qual è la differenza tra i primi due e gli ultimi due?


3
Questo link mi ha aiutato blog.mgechev.com/2016/01/23/… dopo aver letto le risposte di seguito. Saluti :)
Gopinath Shiva,

Risposte:


256

Risponderò alla tua domanda utilizzando la terminologia Shadow DOM e Light DOM (proviene da componenti Web, vedi di più qui ). In generale:

  • Shadow DOM : è un DOM interno del componente definito dall'utente (come creatore del componente ) e nascosto da un utente finale. Per esempio:
@Component({
  selector: 'some-component',
  template: `
    <h1>I am Shadow DOM!</h1>
    <h2>Nice to meet you :)</h2>
    <ng-content></ng-content>
  `;
})
class SomeComponent { /* ... */ }
  • DOM leggero : è un DOM che un utente finale del componente fornisce al componente. Per esempio:
@Component({
  selector: 'another-component',
  directives: [SomeComponent],
  template: `
    <some-component>
      <h1>Hi! I am Light DOM!</h1>
      <h2>So happy to see you!</h2>
    </some-component>
  `
})
class AnotherComponent { /* ... */ }

Quindi, la risposta alla tua domanda è piuttosto semplice:

La differenza tra @ViewChildrene @ContentChildrenè che @ViewChildrencercano elementi in Shadow DOM mentre cercali @ContentChildrenin Light DOM.


10
La voce del blog blog.mgechev.com/2016/01/23/… di Minko Gechew ha più senso per me. @ContentChildren sono i bambini, inseriti dalla proiezione dei contenuti (i bambini tra <ng-content> </ng-content>). Dal blog di Minkos: "D'altra parte, ** gli elementi utilizzati tra i tag di apertura e chiusura dell'elemento host di un determinato componente sono chiamati * content children **." Shadow DOM e view incapsulation in Angular2 sono descritti qui: blog.thoughtram.io/angular/2015/06/29/… .
ovest o

4
Per me sembra che @TemplateChildren(invece di @ViewChildren) o @HostChildren(invece di @ContentChildren) sarebbero stati nomi molto migliori, poiché in un tale contesto tutto ciò di cui stiamo parlando è legato alla vista, e anche il wrt binding è legato al contenuto.
superjos

35
@ViewChildren== tuo figlio; @ContentChildren== qualcun altro figlio
candidJ

107

Come suggerisce il nome, @ContentChilde la @ContentChildrenquery torneranno direttive esistenti all'interno del <ng-content></ng-content>elemento della vostra vista, mentre @ViewChilde @ViewChildrenguardare solo a elementi che sono sul vostro modello di vista direttamente.


Quindi usa @ViewChild (ren) a meno che tu non abbia componenti nella tua vista, nel qual caso ricorrere a @ContentChild (ren)?
Ben Taliadoros,

31

Questo video di Angular Connect ha eccellenti informazioni su ViewChildren, ViewChild, ContentChildren e ContentChild https://youtu.be/4YmnbGoh49U

@Component({
  template: `
    <my-widget>
      <comp-a/>
    </my-widget>
`
})
class App {}

@Component({
  selector: 'my-widget',
  template: `<comp-b/>`
})
class MyWidget {}

Dal my-widgetpunto di vista, comp-aè l ' ContentChilded comp-bè l' ViewChild. CompomentChildrene ViewChildrenrestituisce un iterabile mentre xChild restituisce una singola istanza.


Questa è la spiegazione migliore. Grazie :)
Javeed

Hai fatto un esempio chiaro e semplice, ma il modello di MyWidget dovrebbe essere <comp-b><ng-content></ng-content></comp-b>giusto?
Ark

1

Facciamo un esempio, abbiamo un componente home e un componente figlio e all'interno un componente figlio un componente figlio piccolo.

<home>
     <child>
           <small-child><small-child>
     </child>
</home>

Ora puoi prendere tutti gli elementi figlio nel contesto del componente home con @viewChildren perché questi vengono aggiunti direttamente nel modello del componente home. Tuttavia, quando si tenta di accedere <small-child>all'elemento dal contesto del componente figlio, non è possibile accedervi perché non viene aggiunto direttamente all'interno del modello del componente figlio. Viene aggiunto attraverso la proiezione del contenuto nel componente figlio per componente home. È qui che entra in gioco @contentChild e puoi afferrarlo con @contentChild.

La differenza si verifica quando si tenta di accedere al riferimento agli elementi nel controller. Puoi accedere a tutti gli elementi che vengono aggiunti direttamente nel modello del componente da @viewChild. Ma non puoi afferrare il riferimento agli elementi proiettati con @viewChild Per accedere agli elementi proiettati devi usare @contentChild.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.