【问题标题】:Angular 8 - @ViewChild returns undefined on parent component. (no nested ngIf and called in ngAfterViewInit)Angular 8 - @ViewChild 在父组件上返回未定义。 (没有嵌套的 ngIf 并在 ngAfterViewInit 中调用)
【发布时间】:2020-08-02 06:11:17
【问题描述】:

希望有人能启发我。

问题

我需要获取对放置在内部组件中的指令的引用。 我正在使用 @ViewChild 定位 Directive 类,使用 {static:true} 因为它不必等待状态更改并稍后在用户单击按钮时在生命周期中使用它。

@ViewChild(DirectiveClass, {static:true}) childRef : DirectiveClass;

预期

事件发生时在 childRef 实例变量中有指令引用。

实际

childRef 是undefined

我对类似问题进行了研究,似乎都是因为 ref 在 *ngIf 内,应该是 {static: false};或者因为 ref 打算在它被获取之前使用(在 ngAfterViewInit 钩子之前)。情况并非如此,这种情况相当简单,但又不会出错! :/

复制

情况

所以,我得到了两个组件和一个指令。让我们称它们为 ParentComponent 和 SonComponent。子组件中应用了指令,所以我们称它为 SonDirective。

基本上就是这样的结构。

<app-parent>
  <app-son> </app-son> //<- Directive inside
</app-parent>

代码

//parent.component.ts
@Component({
  selector: 'app-parent',
  template: `
    <div>
      <h2> parent </h2>
      <app-son></app-son>
    </div>
  `,
})
export class AppParentComponent implements AfterViewInit{

  @ViewChild(AppSonDirective,{static: true}) childRef : AppSonDirective;
  constructor() {}
  ngAfterViewInit() {
    console.log("childRef:",this.childRef)
  }
}
// son.component.ts
@Component({
  selector: 'app-son',
  template: `
    <div appSonDirective>
      <p> son <p>
    </div>
  `,
})
export class AppSonComponent {
  constructor() {}
}

//son.directive.ts
@Directive({
    selector: '[appSonDirective]'
})
export class AppSonDirective {
constructor(){}
}

注意: 如果我将视图子引用移动到子组件,则可以访问它。问题似乎出在父组件(?)

无论如何...here 是复制代码(它有一些日志可以知道发生了什么)

任何想法都会有所帮助。

提前致谢! :)

【问题讨论】:

    标签: javascript angular typescript viewchild


    【解决方案1】:

    问题是@ViewChild 仅在组件 DOM 周围工作,但无法访问其子组件的 DOM,这会破坏组件之间的封装。在这种情况下,appSonDirectiveAppSonComponent DOM 中声明,但是因为您试图从AppParentComponent 访问它,所以它返回undefined,因为AppParentComponent 无法访问AppSonComponent DOM。如果你有这样的东西,它可以工作:

    <app-parent>
      <app-son appSonDirective></app-son> 
    </app-parent>
    

    一种解决方案是将指令公开为子组件的属性。比如:

    @Component({
      selector: 'app-son',
      template: `
        <div appSonDirective>
          <p> son <p>
        </div>
      `,
    })
    export class AppSonComponent {
      @ViewChild(AppSonDirective,{static: true}) childRef : AppSonDirective;
      constructor() {}
    }
    

    然后在AppParentComponent

    @Component({
      selector: 'app-parent',
      template: `
        <div>
          <h2> parent </h2>
          <app-son></app-son>
        </div>
      `,
    })
    export class AppParentComponent implements AfterViewInit{
    
      @ViewChild(AppSonComponent,{static: true}) son : AppSonComponent;
      constructor() {}
      ngAfterViewInit() {
        console.log("childRef:",this.son.childRef)
      }
    

    }

    【讨论】:

    • 首先...感谢您这么快的回答!我认为这种观点 child refs 绕过了这种封装。但是现在您提到,它没有感觉(与儿子方法相同)。所以......要么从子组件公开或进行一些重构。谢谢!!
    • @chudix 很高兴为您提供帮助!
    猜你喜欢
    • 2019-06-23
    • 2019-10-19
    • 2021-07-26
    • 2020-03-25
    • 2017-11-16
    • 1970-01-01
    • 2017-11-25
    • 2017-01-08
    • 2019-07-28
    相关资源
    最近更新 更多