Яка різниця між @ViewChild та @ContentChild?


189

Кутова 2 передбачає @ViewChild, @ViewChildren, @ContentChildі @ContentChildrenдекоратор для запиту нащадків елементів відображення компонента.

Яка різниця між першими двома та останніми двома?


3
Це посилання допомогло мені blog.mgechev.com/2016/01/23/…, прочитавши відповіді нижче. Ура :)
Gopinath Shiva

Відповіді:


256

Я відповім на ваше запитання, використовуючи Shadow DOM та Light DOM термінологію (вона походить з веб-компонентів, докладніше див. Тут ). В загальному:

  • Shadow DOM - це внутрішній DOM вашого компонента, який визначений вами (як творець компонента ) і прихований від кінцевого користувача. Наприклад:
@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 - це DOM, який кінцевий користувач вашого компонента постачає у ваш компонент. Наприклад:
@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 { /* ... */ }

Отже, відповідь на ваше запитання досить простий:

Різниця між @ViewChildrenі @ContentChildrenполягає в тому, що @ViewChildrenшукайте елементи в Shadow DOM, шукаючи @ContentChildrenїх у Light DOM.


10
Запис у блозі blog.mgechev.com/2016/01/23/… від Minko Gechew має для мене більше сенсу. @ContentChildren - це діти, вставлені проекцією контенту (діти між <ng-content> </ng-content>). З блогу Minkos: "З іншого боку, ** елементи, які використовуються між тегами відкриття та закриття хост-елемента певного компонента, називаються * дочірніми вмістами **." Shadow DOM та інкапсуляція перегляду в Angular2 описані тут: blog.thoughtram.io/angular/2015/06/29/… .
westor

4
Для мене це звучить як @TemplateChildren(замість @ViewChildren) або @HostChildren(замість @ContentChildren) були б набагато кращими іменами, оскільки в такому контексті все, про що ми говоримо, стосується перегляду, і прив’язка wrt теж пов'язана зі змістом.
superjos

35
@ViewChildren== ваша власна дитина; @ContentChildren== чужа дитина
відвертаJ

107

Як слід з назви, @ContentChildі @ContentChildrenзапити будуть повертати директиви існуючих всередині <ng-content></ng-content>елемента вашої точки зору, в той час як @ViewChildі @ViewChildrenдивитися тільки на елементах , які знаходяться на вашому шаблоні виду безпосередньо.


Тож використовуйте @ViewChild (ren), якщо у вас немає компонентів, у якому випадку ви переходите до @ContentChild (ren)?
Бен Таліадорос

31

Це відео від Angular Connect має чудову інформацію про ViewChildren, ViewChild, ContentChildren та ContentChild https://youtu.be/4YmnbGoh49U

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

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

З my-widgetточки зору, comp-aє ContentChildі comp-bє ViewChild. CompomentChildrenі ViewChildrenповернути ітерабельний, тоді як xChild повертає один екземпляр.


Це краще пояснення. Дякую :)
Javeed

Ви зробили зрозумілий і простий приклад, але шаблон MyWidget повинен бути <comp-b><ng-content></ng-content></comp-b>правильним?
arjel

1

Візьмемо приклад. У нас є один домашній компонент і один дочірній компонент, а всередині дочірнього компонента - один маленький дочірній компонент.

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

Тепер ви можете захопити всі дочірні елементи в контексті домашнього компонента за допомогою @viewChildren, оскільки вони безпосередньо додаються в шаблон домашнього компонента. Але, коли ви намагаєтесь отримати доступ<small-child> елемента з контексту дочірнього компонента, ви не можете отримати доступ до нього, оскільки він безпосередньо не додається до дочірнього шаблону компонента. Він додається за допомогою проекції вмісту в дочірній компонент на домашній компонент. Тут надходить @contentChild, і ви можете схопити його за допомогою @contentChild.

Різниця виникає при спробі отримати доступ до посилань на елементи в контролері. Ви можете отримати доступ до всіх елементів, які безпосередньо додаються в шаблон компонента, від @viewChild. Але ви не можете захопити посилання на проектовані елементи за допомогою @viewChild Для доступу до проектованого елемента потрібно використовувати @contentChild.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.