Apa perbedaan antara @ViewChild dan @ContentChild?


189

Sudut 2 menyediakan @ViewChild, @ViewChildren, @ContentChilddan @ContentChildrendekorator untuk query elemen keturunan komponen ini.

Apa perbedaan antara dua yang pertama dan yang kedua?


3
Tautan ini membantu saya blog.mgechev.com/2016/01/23/... setelah membaca jawaban di bawah ini. Cheers :)
Gopinath Shiva

Jawaban:


256

Saya akan menjawab pertanyaan Anda menggunakan terminologi Shadow DOM dan Light DOM (itu berasal dari komponen web, lihat lebih lanjut di sini ). Secara umum:

  • Shadow DOM - adalah DOM internal komponen Anda yang ditentukan oleh Anda (sebagai pencipta komponen ) dan disembunyikan dari pengguna akhir. Sebagai contoh:
@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 - adalah DOM yang merupakan pengguna akhir dari pasokan komponen Anda ke dalam komponen Anda. Sebagai contoh:
@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 { /* ... */ }

Jadi, jawaban untuk pertanyaan Anda cukup sederhana:

Perbedaan antara @ViewChildrendan @ContentChildrenadalah bahwa @ViewChildrenmencari elemen di Shadow DOM sambil @ContentChildrenmencari mereka di Light DOM.


10
Entri blog blog.mgechev.com/2016/01/23/... dari Minko Gechew lebih masuk akal bagi saya. @ContentChildren adalah anak-anak, disisipkan oleh proyeksi konten (anak-anak antara <ng-content> </ng-content>). Dari Blog Minkos: "Di sisi lain, elemen ** yang digunakan antara tag pembuka dan penutup elemen host dari komponen yang diberikan disebut * konten anak **." Bayangkan DOM dan lihat enkapsulasi dalam Angular2 dijelaskan di sini: blog.thoughtram.io/angular/2015/06/29/… .
Barat atau

4
Bagi saya kedengarannya seperti @TemplateChildren(bukan @ViewChildren) atau @HostChildren(bukannya @ContentChildren) akan menjadi nama yang jauh lebih baik, karena dalam konteks seperti itu semua yang kita bicarakan terkait dengan tampilan, dan pengikatan juga terkait konten.
superjos

35
@ViewChildren== anak Anda sendiri; @ContentChildren== Seseorang anak lain
jujur

107

Seperti namanya, @ContentChilddan @ContentChildrenkueri akan mengembalikan arahan yang ada di dalam <ng-content></ng-content>elemen tampilan Anda, sedangkan @ViewChilddan @ViewChildrenhanya melihat elemen yang ada di template tampilan Anda secara langsung.


Jadi gunakan @ViewChild (ren) kecuali Anda memiliki komponen dalam tampilan Anda dalam hal mana kembali ke @ContentChild (ren)?
Ben Taliadoros

31

Video dari Angular Connect ini memiliki info bagus tentang ViewChildren, ViewChild, ContentChildren, dan ContentChild https://youtu.be/4YmnbGoh49U

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

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

Dari my-widgetperspektif, comp-aadalah ContentChilddan comp-badalah ViewChild. CompomentChildrendan ViewChildrenkembalikan iterable sementara xChild mengembalikan satu instance.


Ini penjelasan yang lebih baik. Terima kasih :)
Javeed

Anda membuat contoh yang jelas dan sederhana, tetapi templat MyWidget seharusnya <comp-b><ng-content></ng-content></comp-b>benar?
arjel

1

Mari kita ambil contoh, Kami memiliki satu komponen rumah dan satu komponen anak dan di dalam komponen anak satu komponen anak kecil.

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

Sekarang Anda dapat mengambil semua elemen anak dalam konteks komponen rumah dengan @viewChildren karena ini ditambahkan langsung ke templat komponen rumah. Tetapi, ketika Anda mencoba mengakses <small-child>elemen dari konteks komponen anak maka Anda tidak dapat mengaksesnya karena tidak secara langsung ditambahkan dalam templat komponen anak. Itu ditambahkan melalui proyeksi konten menjadi komponen anak oleh komponen rumah. Di sinilah @contentChild masuk dan Anda dapat mengambilnya dengan @contentChild.

Perbedaan terjadi ketika Anda mencoba mengakses referensi elemen di controller. Anda dapat mengakses ambil semua elemen yang langsung ditambahkan ke template komponen oleh @viewChild. Tetapi Anda tidak dapat mengambil referensi elemen yang diproyeksikan dengan @viewChild Untuk mengakses elemen yang diproyeksikan, Anda harus menggunakan @contentChild.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.