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?

menggambar moore
sumber
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.

alexpods
sumber
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.

menggambar moore
sumber
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.

mithun_daa
sumber
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.

dev verma
sumber