【问题标题】:@ViewChild: access grand-child methods@ViewChild:访问孙子方法
【发布时间】:2016-08-07 20:23:09
【问题描述】:

我有三个嵌套组件,分别称为level0level1level2,定义如下:

@Component({
selector: 'level2',
template: `<div>I am level 2</div>`,
})
export class Level2 {
  getName(){
    return "my name is 'TWO'";
  }
}

@Component({
selector: 'level1',
template: `<div>I am level 1<level2></level2></div>`,
directives: [Level2]
})
export class Level1 {
  getName(){
    return "my name is 'ONE'";
  }
}

@Component({
selector: 'level0',
template: `<div>I am level 0<level1></level1></div>`,
directives: [Level1,Level2]
})
export class App {
@ViewChild(Level1) level1:Level1;
@ViewChild(Level2) level2:Level2;
ngAfterViewInit() {
  if(this.level1){var name1 = this.level1.getName();}
  if(this.level2){var name2 = this.level2.getName();}
  console.log("name1",name1);
  console.log("name2",name2);
  }
}

在控制台中,我希望看到:

name1 my name is 'ONE'
name2 my name is 'TWO'

但我看到的是:

name1 my name is 'ONE'
name2 undefined

我错过了什么?为什么Level0组件不能通过@ViewChild访问Level2

有没有办法访问Level0 中的Level2 方法?


Here is the plnkr

【问题讨论】:

    标签: angular typescript angular2-directives viewchild


    【解决方案1】:

    如果你在嵌套组件的每一层都使用 ViewChild 就可以实现,就像这样:

    // Level 2
    @Component({
    selector: 'level2',
    template: `<div>I am level 2</div>`,
    })
    export class Level2 {
      getName(){
        return "my name is 'TWO'";
      }
    }
    
    
    // Level 1
    @Component({
    selector: 'level1',
    template: `<div>I am level 1<level2></level2></div>`,
    directives: [Level2]
    })
    export class Level1 {
      @ViewChild(Level2) level2:Level2;
      getName(){
        return "my name is 'ONE'";
      }
    
      // You need to add additional function that would be called from level 1
      calledFromLevel1() {
        return this.level2.getName();
      }
    }
    
    
    // Level 0
    @Component({
    selector: 'level0',
    template: `<div>I am level 0<level1></level1></div>`,
    directives: [Level1,Level2]
    })
    export class App {
    @ViewChild(Level1) level1:Level1;
    ngAfterViewInit() {
      if(this.level1) {
        var name1 = this.level1.getName();
        var name2 = this.level1.calledFromLevel1();
      }
      console.log("name1",name1);
      console.log("name2",name2);
      }
    }
    

    【讨论】:

      【解决方案2】:

      我认为目前不可能。

      ViewQueryMetadata API doc 表示如下:

      支持与 QueryMetadata 相同的查询参数,后代除外

      QueryMetadata API doc 有这个后代示例:

      通过使用descendants 参数配置查询是查找查询元素的直接子代还是查询元素的所有后代。默认设置为false。

      ...此处未显示代码...

      在查询项目时,第一个容器默认只能看到 a 和 b,但 Query(TextDirective, {descendants: true}) 也会看到 c。

      【讨论】:

      • @Manube,我想你会失望的。我相信 Query 已被弃用,取而代之的是 ViewChild 和 ViewChildren。如果 Query 还在,我认为它不支持descendants。 (在回答这个问题之前,我尝试在 Plunker 中使用它,但我无法让它工作。)
      • 好吧,那我试试换个思路。由于我希望实现一个应用程序,其中父级应该知道其所有选定的嵌套后代,我想我只会将数据保留在服务中并将它们注入父级
      • @MarkRajcok 链接已损坏,您能更新您的答案吗?
      • @stackdave 我相信查询功能现在已完全弃用;你不会在上面找到任何文档。正如上面第二条评论所提到的,必须使用 ViewChild 和 ContentChild,它们没有后代查询能力。
      猜你喜欢
      • 2020-11-11
      • 2017-03-01
      • 1970-01-01
      • 2017-03-03
      • 2018-01-30
      • 2020-05-09
      • 2018-12-09
      • 1970-01-01
      • 2020-12-01
      相关资源
      最近更新 更多