Jaka jest różnica między @ViewChild a @ContentChild?

189

Kątowa 2 zapewnia @ViewChild, @ViewChildren, @ContentChildi @ContentChildrendekoratorów dla zapytań elementów potomnych danego składnika.

Jaka jest różnica między dwoma pierwszymi a dwoma ostatnimi?

narysował Moore
źródło
3
Ten link pomógł mi blog.mgechev.com/2016/01/23/… po przeczytaniu poniższych odpowiedzi. Na zdrowie :)
Gopinath Shiva

Odpowiedzi:

256

Odpowiem na twoje pytanie za pomocą terminologii Shadow DOM i Light DOM (pochodzi ona z komponentów internetowych, więcej informacji tutaj ). Ogólnie:

  • Shadow DOM - to wewnętrzny DOM twojego komponentu, który jest zdefiniowany przez ciebie (jako twórcę komponentu ) i ukryty przed użytkownikiem końcowym. Na przykład:
@Component({
  selector: 'some-component',
  template: `
    <h1>I am Shadow DOM!</h1>
    <h2>Nice to meet you :)</h2>
    <ng-content></ng-content>
  `;
})
class SomeComponent { /* ... */ }
  • Lekki DOM - to DOM, który użytkownik końcowy twojego komponentu dostarcza do swojego komponentu. Na przykład:
@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 { /* ... */ }

Tak więc odpowiedź na twoje pytanie jest dość prosta:

Różnica między @ViewChildreni @ContentChildrenpolega na tym, że @ViewChildrenszukają elementów w Shadow DOM, a @ContentChildrenszukają ich w Light DOM.

alexpods
źródło
10
Wpis na blogu blog.mgechev.com/2016/01/23/... od Minko Gechew ma dla mnie większy sens. @ContentChildren to dzieci, wstawiane przez projekcję treści (dzieci między <ng-content> </ng-content>). Z blogu Minkos: „Z drugiej strony ** elementy, które są używane między otwierającymi i zamykającymi znacznikami elementu hosta danego komponentu, nazywane są * elementami potomnymi **.” Shadow DOM i enkapsulacja widoku w Angular2 są opisane tutaj: blog.thoughtram.io/angular/2015/06/29/… .
zachodni
4
Dla mnie to brzmi jak @TemplateChildren(zamiast @ViewChildren) lub @HostChildren(zamiast @ContentChildren) byłyby znacznie lepszymi nazwami, ponieważ w takim kontekście wszystko, o czym mówimy, jest związane z widokiem, a wiązanie wrt jest również związane z treścią.
superjos,
35
@ViewChildren== twoje własne dziecko; @ContentChildren== czyjeś dziecko
szczeryJ
107

Jak sama nazwa wskazuje, @ContentChildi @ContentChildrenzapytań powróci dyrektyw istniejących wewnątrz <ng-content></ng-content>elementu widoku, podczas gdy @ViewChildi @ViewChildrentylko patrzeć na te elementy, które na widok szablonu bezpośrednio.

narysował Moore
źródło
Więc użyj @ViewChild (ren), chyba że masz komponenty w swoim widoku, w którym to przypadku powróć do @ContentChild (ren)?
Ben Taliadoros
31

Ten film wideo od Angular Connect zawiera doskonałe informacje o ViewChildren, ViewChild, ContentChildren i ContentChild https://youtu.be/4YmnbGoh49U

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

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

Z my-widgetperspektywy comp-ajest ContentChildi comp-bjest ViewChild. CompomentChildreni ViewChildrenzwracamy iterowalność, podczas gdy xChild zwraca pojedynczą instancję.

mithun_daa
źródło
To jest lepsze wytłumaczenie. Dzięki :)
Javeed
Dałeś jasny i prosty przykład, ale szablon MyWidget powinien mieć <comp-b><ng-content></ng-content></comp-b>rację?
arjel
1

Weźmy przykład: Mamy jeden komponent domowy i jeden komponent potomny, a wewnątrz komponent potomny jeden mały komponent potomny.

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

Teraz możesz pobrać wszystkie elementy potomne w kontekście komponentu domowego za pomocą @viewChildren, ponieważ są one dodawane bezpośrednio w szablonie komponentu domowego. Jednak podczas próby uzyskania dostępu do <small-child>elementu z kontekstu komponentu podrzędnego nie można uzyskać do niego dostępu, ponieważ nie jest on dodawany bezpośrednio w szablonie komponentu podrzędnego. Jest dodawany poprzez projekcję treści do komponentu potomnego według komponentu domowego. W tym miejscu pojawia się @contentChild i możesz go pobrać za pomocą @contentChild.

Różnica występuje, gdy próbujesz uzyskać dostęp do referencji elementów w kontrolerze. Możesz uzyskać dostęp do grab wszystkich elementów, które są bezpośrednio dodawane do szablonu komponentu przez @viewChild. Ale nie można pobrać odniesienia do rzutowanych elementów za pomocą @viewChild Aby uzyskać dostęp do rzutowanego elementu, należy użyć @contentChild.

dev verma
źródło