【问题标题】:Getting reference to child component in parent component [duplicate]在父组件中获取对子组件的引用[重复]
【发布时间】:2016-07-01 07:37:26
【问题描述】:

在 Angular 2 中,我有一个包含子组件的组件。但是,我想获取该子组件的副本以在父组件中使用、调用其函数或其他任何内容。

我发现我可以使用局部变量,这样我就可以使用模板中的组件。但是,我不只是在模板中使用它,我想在组件的实际代码中使用它。

我找到了一种方法,这是子代码:

//our child
import {Component, OnInit, EventEmitter} from 'angular2/core'

@Component({
  selector: 'my-child',
  providers: [],
  template: `
    <div>
      <h2>Child</h2>

    </div>
  `,
  directives: [],
  outputs: ['onInitialized']
})

export class Child implements OnInit{

  onInitialized = new EventEmitter<Child>();

  constructor() {
    this.name = 'Angular2'
  }

  ngOnInit() {
    this.onInitialized.emit(this);
  }
}

家长:

//our root app component
import {Component} from 'angular2/core'
import {Child} from './child'

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <my-child (onInitialized)="func($event)"></my-child>
    </div>
  `,
  directives: [Child]
})
export class App {
  constructor() {
    this.name = 'Angular2'
  }

  func(e) {
    console.log(e)

  }
}

我在this plunker 中实现了它。但这似乎是一个 hack。

难道没有更简单的方法可以将组件附加到其父级中的变量吗?

【问题讨论】:

    标签: angular typescript angular-template


    【解决方案1】:

    您可以使用ViewChild

    <child-tag #varName></child-tag>
    
    @ViewChild('varName') someElement;
    
    ngAfterViewInit() {
      someElement...
    }
    

    其中varName 是添加到元素的模板变量。或者,您可以按组件或指令类型查询。

    还有ViewChildrenContentChildContentChildren等替代方案。

    @ViewChildren也可以在构造函数中使用。

    constructor(@ViewChildren('var1,var2,var3') childQuery:QueryList)
    

    优点是结果更早。

    另请参阅http://www.bennadel.com/blog/3041-constructor-vs-property-querylist-injection-in-angular-2-beta-8.htm,了解使用构造函数或字段的一些优点/缺点。

    注意:@Query()@ContentChildren() 的已弃用前身

    更新

    Query 目前只是一个抽象基类。没查到有没有用https://github.com/angular/angular/blob/2.1.x/modules/@angular/core/src/metadata/di.ts#L145

    【讨论】:

    • 感谢您的回答。只是一个要确定的问题,我的组件是递归的,孩子会有孩子等等。 ViewChildren 是否获得所有递归树?还是只是第一级(实际模板中的那个)?
    • 另外,一些组件是使用 ngIf 包含的,所以在创建父级时它们不会立即出现,这会改变什么吗?
    • AFAIK 当元素实际存在于 DOM 中时,它们包含在 QueryList 中。当 ngIf 为 false 时,将其从列表中删除。
    • @Gunter - 在@ViewChild('varName') someElement 中,如果孩子是SomeComponent 类型,那么Angular 会自动知道someElementSomeComponent 类型?您的答案有效,我只是想确定一下。只是为了让事情更明确,似乎我也可以这样做@ViewChild('varName') someElement:SomeComponent
    • @ManuChadha 当然,更明确通常更好,因为更早发现错误并且自动完成和重构效果更好。
    【解决方案2】:

    您实际上可能会选择 ViewChild API...

    parent.ts

    <button (click)="clicked()">click</button>
    
    export class App {
      @ViewChild(Child) vc:Child;
      constructor() {
        this.name = 'Angular2'
      }
    
      func(e) {
        console.log(e)
    
      }
      clicked(){
       this.vc.getName();
      }
    }
    

    child.ts

    export class Child implements OnInit{
    
      onInitialized = new EventEmitter<Child>();
      ...  
      ...
      getName()
      {
         console.log('called by vc')
         console.log(this.name);
      }
    }
    

    【讨论】:

      【解决方案3】:

      您需要利用 @ViewChild 装饰器通过注入从父组件引用子组件:

      import { Component, ViewChild } from 'angular2/core';  
      
      (...)
      
      @Component({
        selector: 'my-app',
        template: `
          <h1>My First Angular 2 App</h1>
          <child></child>
          <button (click)="submit()">Submit</button>
        `,
        directives:[App]
      })
      export class AppComponent { 
        @ViewChild(Child) child:Child;
      
        (...)
      
        someOtherMethod() {
          this.searchBar.someMethod();
        }
      }
      

      这是更新的 plunkr:http://plnkr.co/edit/mrVK2j3hJQ04n8vlXLXt?p=preview

      您可以注意到@Query 参数装饰器也可以使用:

      export class AppComponent { 
        constructor(@Query(Child) children:QueryList<Child>) {
          this.childcmp = children.first();
        }
      
        (...)
      }
      

      【讨论】:

        猜你喜欢
        • 2017-05-25
        • 2020-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-05
        • 2018-03-18
        • 1970-01-01
        相关资源
        最近更新 更多