Qual é a diferença entre @ViewChild e @ContentChild?

189

Angular 2 proporciona @ViewChild, @ViewChildren, @ContentChilde @ContentChildrendecoradores para consultar elementos descendentes de um componente.

Qual é a diferença entre os dois primeiros e os dois últimos?

chamou moore
fonte
3
Este link me ajudou a blog.mgechev.com/2016/01/23/… depois de ler as respostas abaixo. Cheers :)
Gopinath Shiva

Respostas:

256

Responderei sua pergunta usando as terminologias Shadow DOM e Light DOM (elas vieram de componentes da Web, veja mais aqui ). Em geral:

  • Shadow DOM - é um DOM interno do seu componente que é definido por você (como criador do componente ) e oculto ao usuário final. Por exemplo:
@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 - é um DOM que um usuário final do seu componente fornece ao seu componente. Por exemplo:
@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 { /* ... */ }

Portanto, a resposta para sua pergunta é bem simples:

A diferença entre @ViewChildrene @ContentChildrené @ViewChildrenprocurar elementos no Shadow DOM e @ContentChildrenprocurá-los no Light DOM.

alexpods
fonte
10
A entrada do blog blog.mgechev.com/2016/01/23/… de Minko Gechew faz mais sentido para mim. @ContentChildren são os filhos, inseridos pela projeção de conteúdo (os filhos entre <ng-content> </ng-content>). Do blog Minkos: "Por outro lado, ** os elementos usados ​​entre as tags de abertura e fechamento do elemento host de um determinado componente são chamados * filhos de conteúdo **." O DOM de sombra e o encapsulamento de visualização no Angular2 são descritos aqui: blog.thoughtram.io/angular/2015/06/06/29/… .
westor 27/04
4
Para mim, parece que @TemplateChildren(em vez de @ViewChildren) ou @HostChildren(em vez de @ContentChildren) teriam nomes muito melhores, pois nesse contexto tudo o que estamos falando é relacionado à exibição e a ligação wrt também está relacionada ao conteúdo.
Superjo
35
@ViewChildren== seu próprio filho; @ContentChildren== alguém de outra criança
candidJOff
107

Como o nome sugere, @ContentChilde @ContentChildrenconsultas retornará directivas existentes no interior do <ng-content></ng-content>elemento de sua vista, enquanto @ViewChilde @ViewChildrensó olhar para os elementos que estão no seu modelo de visão diretamente.

chamou moore
fonte
Portanto, use @ViewChild (ren), a menos que você tenha componentes em sua exibição. Nesse caso, volte a @ContentChild (ren)?
Ben Taliadoros
31

Este vídeo do Angular Connect tem informações excelentes sobre ViewChildren, ViewChild, ContentChildren e ContentChild https://youtu.be/4YmnbGoh49U

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

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

Da my-widgetperspectiva de, comp-aé o ContentChilde comp-bé o ViewChild. CompomentChildrene ViewChildrenretorne um iterável enquanto o xChild retorna uma única instância.

mithun_daa
fonte
Esta é a melhor explicação. Obrigado :)
Javeed
Você fez um exemplo claro e simples, mas o modelo do MyWidget deve estar <comp-b><ng-content></ng-content></comp-b>certo?
arjel 01/07
1

Vamos dar um exemplo: temos um componente doméstico e um componente filho e, dentro do componente filho, um componente filho pequeno.

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

Agora você pode pegar todos os elementos filhos no contexto do componente inicial com @viewChildren, porque eles são adicionados diretamente no modelo do componente inicial. Mas, quando você tenta acessar o <small-child>elemento do contexto do componente filho, não é possível acessá-lo porque ele não é adicionado diretamente ao modelo do componente filho. É adicionado através da projeção de conteúdo no componente filho pelo componente inicial. É aqui que o @contentChild entra e você pode acessá-lo com @contentChild.

A diferença ocorre quando você tenta acessar a referência de elementos no controlador. Você pode acessar todos os elementos que são adicionados diretamente ao modelo do componente pelo @viewChild. Mas você não pode pegar a referência de elementos projetados com @viewChild Para acessar o elemento projetado, você deve usar @contentChild.

dev verma
fonte