Was ist der Unterschied zwischen @ViewChild und @ContentChild?

187

Angular 2 bietet @ViewChild, @ViewChildren, @ContentChildund @ContentChildrenDekorateure für eine Komponente der untergeordneten Elemente abfragt.

Was ist der Unterschied zwischen den ersten beiden und den beiden letzteren?

zog mehr
quelle
3
Dieser Link hat mir geholfen, blog.mgechev.com/2016/01/23/… nach dem Lesen der folgenden Antworten. Prost :)
Gopinath Shiva

Antworten:

254

Ich beantworte Ihre Frage mit der Shadow DOM- und Light DOM- Terminologie (sie stammt von Webkomponenten, mehr dazu hier ). Allgemein:

  • Schatten-DOM - ist ein internes DOM Ihrer Komponente, das von Ihnen (als Ersteller der Komponente ) definiert und vor einem Endbenutzer verborgen wird. Beispielsweise:
@Component({
  selector: 'some-component',
  template: `
    <h1>I am Shadow DOM!</h1>
    <h2>Nice to meet you :)</h2>
    <ng-content></ng-content>
  `;
})
class SomeComponent { /* ... */ }
  • Light DOM - ist ein DOM, das ein Endbenutzer Ihrer Komponente in Ihre Komponente einspeist. Beispielsweise:
@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 { /* ... */ }

Die Antwort auf Ihre Frage ist also ziemlich einfach:

Der Unterschied zwischen @ViewChildrenund @ContentChildrenbesteht darin, dass @ViewChildrenin Shadow DOM nach Elementen gesucht wird, während @ContentChildrenin Light DOM nach Elementen gesucht wird.

Alexpods
quelle
10
Der Blogeintrag blog.mgechev.com/2016/01/23/… von Minko Gechew macht für mich mehr Sinn. @ContentChildren sind die untergeordneten Elemente, die durch Inhaltsprojektion eingefügt werden (die untergeordneten Elemente zwischen <ng-content> </ ng-content>). Aus dem Minkos-Blog: "Andererseits werden ** Elemente, die zwischen den öffnenden und schließenden Tags des Host-Elements einer bestimmten Komponente verwendet werden, als * untergeordnete Elemente ** bezeichnet." Das Shadow DOM und die Ansichtskapselung in Angular2 werden hier beschrieben: blog.ilsttram.io/angular/2015/06/29/… .
Westor
4
Für mich klingt es so , als wären @TemplateChildren(anstelle von @ViewChildren) oder @HostChildren(anstelle von @ContentChildren) viel bessere Namen gewesen, da in einem solchen Kontext alles, worüber wir sprechen, auf die Ansicht bezogen ist und die Wrt-Bindung auch auf den Inhalt.
Superjos
34
@ViewChildren== dein eigenes Kind; @ContentChildren== jemand anderes Kind
CandidJ
105

Wie der Name schon sagt, @ContentChildund @ContentChildrenAbfragen werden Richtlinien zurückkehren innerhalb des bestehenden <ng-content></ng-content>Elements Ihrer Ansicht, während @ViewChildund @ViewChildrennur auf Elemente suchen , die direkt auf Ihrer Ansicht Vorlage sind.

zog mehr
quelle
Verwenden Sie also @ViewChild (ren), es sei denn, Sie haben Komponenten in Ihrer Ansicht. In diesem Fall greifen Sie auf @ContentChild (ren) zurück.
Ben Taliadoros
31

Dieses Video von Angular Connect enthält hervorragende Informationen zu ViewChildren, ViewChild, ContentChildren und ContentChild https://youtu.be/4YmnbGoh49U

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

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

Aus my-widgetder Sicht comp-aist das ContentChildund comp-bist das ViewChild. CompomentChildrenund ViewChildrengeben Sie eine iterable zurück, während xChild eine einzelne Instanz zurückgibt.

mithun_daa
quelle
Dies ist die bessere Erklärung. Danke :)
Javeed
Sie haben ein klares und einfaches Beispiel gemacht, aber die Vorlage von MyWidget sollte <comp-b><ng-content></ng-content></comp-b>richtig sein?
Arjel vor
1

Nehmen wir ein Beispiel: Wir haben eine Home-Komponente und eine untergeordnete Komponente und innerhalb der untergeordneten Komponente eine kleine untergeordnete Komponente.

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

Jetzt können Sie mit @viewChildren alle untergeordneten Elemente im Kontext der Home-Komponente abrufen, da diese direkt in der Vorlage der Home-Komponente hinzugefügt werden. Wenn Sie jedoch versuchen, <small-child>über den Kontext der untergeordneten Komponente auf ein Element zuzugreifen , können Sie nicht darauf zugreifen, da es nicht direkt in der Vorlage für die untergeordnete Komponente hinzugefügt wird. Es wird durch Inhaltsprojektion in die untergeordnete Komponente von der Home-Komponente hinzugefügt. Hier kommt @contentChild ins Spiel und Sie können es mit @contentChild abrufen.

Der Unterschied tritt auf, wenn Sie versuchen, auf die Elementreferenz im Controller zuzugreifen. Sie können auf Grab greifen, um alle Elemente zu erfassen, die von @viewChild direkt zur Vorlage der Komponente hinzugefügt werden. Mit @viewChild können Sie jedoch keine Referenz für projizierte Elemente abrufen. Um auf projizierte Elemente zugreifen zu können, müssen Sie @contentChild verwenden.

dev verma
quelle