简体   繁体   中英

What's the difference between @ViewChild and @ContentChild?

Angular 2 provides @ViewChild , @ViewChildren , @ContentChild and @ContentChildren decorators for querying a component's descendant elements.

What's the difference between the first two and the latter two?

I'll answer your question using Shadow DOM and Light DOM terminology (it have come from web components, see more here ). In general:

  • Shadow DOM - is an internal DOM of your component that is defined by you (as a creator of the component ) and hidden from an end-user. For example:
@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 - is a DOM that an end-user of your component supply into your component. For example:
@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 { /* ... */ }

So, the answer to your question is pretty simple:

The difference between @ViewChildren and @ContentChildren is that @ViewChildren look for elements in Shadow DOM while @ContentChildren look for them in Light DOM.

顾名思义, @ContentChild@ContentChildren查询将返回@ContentChildren<ng-content></ng-content>元素中存在的指令,而@ViewChild@ViewChildren只直接查看视图模板上的元素.

This video from Angular Connect has excellent info about ViewChildren, ViewChild, ContentChildren and ContentChild https://youtu.be/4YmnbGoh49U

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

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

From my-widget 's perspective, comp-a is the ContentChild and comp-b is the ViewChild . CompomentChildren and ViewChildren return an iterable while the xChild return a single instance.

Lets take a example, We have one home component and one child component and inside child component one small child component.

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

Now you can grab all children elements in context of home component with @viewChildren because these are directly added in template of home component. But, when you try to access <small-child> element from context of child component then you can't access it because it is not directly added within child component template. It is added through content projection into child component by home component. This is where @contentChild comes in and you can grab it with @contentChild.

The difference occur when you try to access elements reference in controller. You can access grab all elements that are directly added into template of component by @viewChild. But you can't grab projected elements reference with @viewChild To access projected element you have to use @contentChild.

只需将 ViewChildren 重命名为 InternalChildren,将 ContentChildren 重命名为 ExternalChildren

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM