Angular 2 提供了 @ViewChild
、@ViewChildren
、@ContentChild
和 @ContentChildren
装饰器来查询组件的后代元素。
前两个和后两个有什么区别?
我将使用 Shadow DOM 和 Light DOM 术语来回答您的问题(它来自网络组件,请参阅更多here)。一般来说:
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 中查找它们。
顾名思义,@ContentChild
和 @ContentChildren
查询将返回存在于视图的 <ng-content></ng-content>
元素中的指令,而 @ViewChild
和 @ViewChildren
仅直接查看视图模板上的元素。
这个来自 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 返回一个实例。
<comp-b><ng-content></ng-content></comp-b>
对吗?
举个例子,我们有一个主组件和一个子组件,在子组件内部有一个小的子组件。
<home>
<child>
<small-child><small-child>
</child>
</home>
现在您可以使用 @viewChildren 获取 home 组件上下文中的所有子元素,因为这些子元素直接添加到 home 组件的模板中。但是,当您尝试从子组件的上下文中访问 <small-child>
元素时,您将无法访问它,因为它不是直接添加到子组件模板中的。它是由 home 组件通过内容投影添加到子组件中的。这就是@contentChild 的用武之地,您可以使用@contentChild 来获取它。
当您尝试访问控制器中的元素引用时,就会出现差异。您可以访问通过@viewChild 直接添加到组件模板中的所有元素。但是您不能使用@viewChild 获取投影元素引用要访问投影元素,您必须使用@contentChild。
只需将 ViewChildren 重命名为 InternalChildren,将 ContentChildren 重命名为 ExternalChildren
@TemplateChildren
(而不是@ViewChildren
)或@HostChildren
(而不是@ContentChildren
)会是更好的名称,因为在这样的上下文中,我们谈论的一切都是与视图相关的,并且wrt 绑定也与内容相关。@ViewChildren
== 你自己的孩子;@ContentChildren
== 别人的孩子