@ViewChild 和 @ContentChild 有啥区别?
Posted
技术标签:
【中文标题】@ViewChild 和 @ContentChild 有啥区别?【英文标题】:What's the difference between @ViewChild and @ContentChild?@ViewChild 和 @ContentChild 有什么区别? 【发布时间】:2016-03-23 11:00:07 【问题描述】:Angular 2 提供了@ViewChild
、@ViewChildren
、@ContentChild
和@ContentChildren
装饰器,用于查询组件的后代元素。
前两者和后两者有什么区别?
【问题讨论】:
此链接在阅读以下答案后帮助了我blog.mgechev.com/2016/01/23/…。干杯:) 【参考方案1】:我将使用 Shadow DOM 和 Light DOM 术语来回答您的问题(它来自 Web 组件,请参阅更多 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 中查找它们。
【讨论】:
Minko Gechew 的博客条目blog.mgechev.com/2016/01/23/… 对我来说更有意义。 @ContentChildren 是孩子,由内容投影插入(@TemplateChildren
(而不是@ViewChildren
)或@HostChildren
(而不是@ContentChildren
)会更好的名字,因为在这种情况下,我们的一切谈论是与视图相关的,并且wrt绑定也与内容相关。
@ViewChildren
== 你自己的孩子; @ContentChildren
== 别人的孩子
@candidJ 今天这是 False,在 ContentChildren 中你有一个默认为 descendants: false 的标志。所以等价是不正确的。
@ViewChild 和 @ContentChild 怎么样?【参考方案2】:
顾名思义,@ContentChild
和 @ContentChildren
查询将返回存在于视图的 <ng-content></ng-content>
元素中的指令,而 @ViewChild
和 @ViewChildren
仅直接查看视图模板上的元素。
【讨论】:
所以使用@ViewChild(ren) 除非您的视图中有组件,在这种情况下回退到@ContentChild(ren)?【参考方案3】:来自 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>
吧?【参考方案4】:
举个例子,我们有一个主组件和一个子组件,在子组件内部有一个小的子组件。
<home>
<child>
<small-child><small-child>
</child>
</home>
现在您可以使用 @viewChildren 获取 home 组件上下文中的所有子元素,因为这些子元素直接添加到 home 组件的模板中。
但是,当您尝试从子组件的上下文中访问 <small-child>
元素时,您将无法访问它,因为它不是直接添加到子组件模板中的。
它是由 home 组件通过内容投影添加到子组件中的。
这就是@contentChild 的用武之地,您可以使用@contentChild 获取它。
当您尝试访问控制器中的元素引用时会发生差异。 您可以访问通过@viewChild 直接添加到组件模板中的所有元素。 但是您无法使用 @viewChild 获取投影元素参考 要访问投影元素,您必须使用 @contentChild。
【讨论】:
【参考方案5】:只需将 ViewChildren 重命名为 InternalChildren,将 ContentChildren 重命名为 ExternalChildren
【讨论】:
以上是关于@ViewChild 和 @ContentChild 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
带有 viewchild 和指令的 Angular 组件测试