Я отвечу на ваш вопрос, используя терминологию 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>`;})classSomeComponent{/* ... */}
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>`})classAnotherComponent{/* ... */}
Итак, ответ на ваш вопрос довольно прост:
Разница между @ViewChildrenи @ContentChildrenзаключается в том, что @ViewChildrenищите элементы в Shadow DOM, а @ContentChildrenищите их в Light DOM.
Запись в блоге blog.mgechev.com/2016/01/23/… от Минько Гечу имеет для меня больше смысла. @ContentChildren - это дочерние элементы, вставляемые проекцией содержимого (дочерние элементы между <ng-content> </ ng-content>). Из блога Minkos: «С другой стороны, ** элементы, которые используются между открывающим и закрывающим тегами хост-элемента данного компонента, называются * content children **." Shadow DOM и представление инкапсуляции в Angular2 описаны здесь: blog.thoughtram.io/angular/2015/06/29/… .
Уэстор
4
Для меня это звучит так, как будто @TemplateChildren(вместо @ViewChildren) или @HostChildren(вместо @ContentChildren) были бы гораздо более подходящие имена, поскольку в таком контексте все, о чем мы говорим, связано с представлением, а также с привязкой к содержимому.
Superjos
35
@ViewChildren== ваш собственный ребенок; @ContentChildren== чей-то еще ребенок
candidJ
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 возвращает один экземпляр.
Вы сделали простой и понятный пример, но шаблон MyWidget должен быть <comp-b><ng-content></ng-content></comp-b>правильным?
Арджел
1
Давайте рассмотрим пример. У нас есть один домашний компонент и один дочерний компонент, а внутри дочернего компонента - один маленький дочерний компонент.
Теперь вы можете захватить все дочерние элементы в контексте домашнего компонента с помощью @viewChildren, потому что они непосредственно добавляются в шаблон домашнего компонента. Но когда вы пытаетесь получить доступ к <small-child>элементу из контекста дочернего компонента, вы не можете получить к нему доступ, потому что он не добавляется непосредственно в шаблон дочернего компонента. Он добавляется через проекцию контента в дочерний компонент домашним компонентом. Вот где приходит @contentChild, и вы можете получить его с помощью @contentChild.
Разница возникает при попытке доступа к элементам ссылки в контроллере. Вы можете получить доступ ко всем элементам, которые непосредственно добавляются в шаблон компонента с помощью @viewChild. Но вы не можете получить ссылку на проецируемые элементы с помощью @viewChild. Для доступа к проецируемому элементу вы должны использовать @contentChild.
Ответы:
Я отвечу на ваш вопрос, используя терминологию Shadow DOM и Light DOM (это пришло из веб-компонентов, подробнее здесь ). В основном:
Итак, ответ на ваш вопрос довольно прост:
источник
@TemplateChildren
(вместо@ViewChildren
) или@HostChildren
(вместо@ContentChildren
) были бы гораздо более подходящие имена, поскольку в таком контексте все, о чем мы говорим, связано с представлением, а также с привязкой к содержимому.@ViewChildren
== ваш собственный ребенок;@ContentChildren
== чей-то еще ребенокКак следует из названия,
@ContentChild
и@ContentChildren
запросы будут возвращать директивы, существующие внутри<ng-content></ng-content>
элемента вашего представления, тогда как@ViewChild
и@ViewChildren
смотреть только на элементы, которые находятся в вашем шаблоне представления напрямую.источник
Это видео от Angular Connect содержит отличную информацию о ViewChildren, ViewChild, ContentChildren и ContentChild https://youtu.be/4YmnbGoh49U
С
my-widget
точки зрения,comp-a
этоContentChild
иcomp-b
естьViewChild
.CompomentChildren
иViewChildren
вернуть итерируемое, в то время как xChild возвращает один экземпляр.источник
<comp-b><ng-content></ng-content></comp-b>
правильным?Давайте рассмотрим пример. У нас есть один домашний компонент и один дочерний компонент, а внутри дочернего компонента - один маленький дочерний компонент.
Теперь вы можете захватить все дочерние элементы в контексте домашнего компонента с помощью @viewChildren, потому что они непосредственно добавляются в шаблон домашнего компонента. Но когда вы пытаетесь получить доступ к
<small-child>
элементу из контекста дочернего компонента, вы не можете получить к нему доступ, потому что он не добавляется непосредственно в шаблон дочернего компонента. Он добавляется через проекцию контента в дочерний компонент домашним компонентом. Вот где приходит @contentChild, и вы можете получить его с помощью @contentChild.Разница возникает при попытке доступа к элементам ссылки в контроллере. Вы можете получить доступ ко всем элементам, которые непосредственно добавляются в шаблон компонента с помощью @viewChild. Но вы не можете получить ссылку на проецируемые элементы с помощью @viewChild. Для доступа к проецируемому элементу вы должны использовать @contentChild.
источник