【问题标题】:What's the difference between ngOnInit and ngAfterViewInit of Angular2?Angular2的ngOnInit和ngAfterViewInit有什么区别?
【发布时间】:2017-04-10 14:00:21
【问题描述】:

我不明白ngOnInitngAfterViewInit 有什么区别。

我发现它们之间的唯一区别是@ViewChild。根据下面的代码,它们中的elementRef.nativeElement是一样的。

我们应该使用什么场景ngAfterViewInit

@Component({
  selector: 'my-child-view',
  template: `
  <div id="my-child-view-id">{{hero}}</div>
  `
})
export class ChildViewComponent {
  @Input() hero: string = 'Jack';
}

//////////////////////
@Component({
  selector: 'after-view',
  template: `
    <div id="after-view-id">-- child view begins --</div>
      <my-child-view [hero]="heroName"></my-child-view>
    <div>-- child view ends --</div>`
    + `
    <p *ngIf="comment" class="comment">
      {{comment}}
    </p>
  `
})
export class AfterViewComponent implements AfterViewInit, OnInit {
  private prevHero = '';
  public heroName = 'Tom';
  public comment = '';

  // Query for a VIEW child of type `ChildViewComponent`
  @ViewChild(ChildViewComponent) viewChild: ChildViewComponent;

  constructor(private logger: LoggerService, private elementRef: ElementRef) {
  }

  ngOnInit() {
    console.log('OnInit');
    console.log(this.elementRef.nativeElement.querySelector('#my-child-view-id'));
    console.log(this.elementRef.nativeElement.querySelector('#after-view-id'));
    console.log(this.viewChild);
    console.log(this.elementRef.nativeElement.querySelector('p'));
  }

  ngAfterViewInit() {
    console.log('AfterViewInit');
    console.log(this.elementRef.nativeElement.querySelector('#my-child-view-id'));
    console.log(this.elementRef.nativeElement.querySelector('#after-view-id'));
    console.log(this.viewChild);
    console.log(this.elementRef.nativeElement.querySelector('p'));
  }
}

【问题讨论】:

    标签: angular ngoninit


    【解决方案1】:

    ngOnInit() 在第一次检查指令的数据绑定属性之后,并且在检查其任何子项之前立即调用。当指令被实例化时,它只被调用一次。

    ngAfterViewInit() 在组件视图及其子视图创建后调用。它是一个生命周期钩子,在组件的视图完全初始化后调用。

    【讨论】:

    • “在组件的视图完全初始化之后”表明这是在 ngOnInit 之后,这是不正确的(可以在 ngOnInit 之前/期间调用 ngAfterViewInit)
    【解决方案2】:

    ngOnInit() 在第一次调用 ngOnChanges() 之后调用。每次更改检测更新输入时都会调用ngOnChanges()

    ngAfterViewInit() 在初始渲染视图后调用。这就是@ViewChild() 依赖它的原因。在呈现之前,您无法访问视图成员。

    【讨论】:

    • 当你说 rendered 时,你的意思是它出现在屏幕上吗? (或发送以呈现在屏幕上)
    • 添加到 DOM 时。如果你设置display: hidden 它直到渲染,但在屏幕上不可见。但是,如果您使用浏览器开发工具调查 DOM,您将能够看到标记。
    • 在呈现之前您无法访问视图成员” - 那么您如何解释 ViewChild (vc) 在 onNgInit 上可用? plnkr.co/edit/AzhRe6bjnuPLKJWEJGwp?p=preview,你能解释一下吗?
    • @Royi 我无法在我的手机上打开你的 Plunker,我需要几天才能回到我的电脑前。 ngOnInit 中已经提供了静态添加的元素。如果您有由 *ngFor 从数据传递到 @Input 呈现的内容,则此内容在 ngOnInit 中尚不可用
    • 非常感谢您的回复。这正是场景。所以我想这就是它。 i.imgur.com/Vbajl4F.jpg 。享受您的假期。
    【解决方案3】:

    内容是作为子项传递的内容。 View 是当前组件的模板。

    视图在内容之前初始化,因此ngAfterViewInit()ngAfterContentInit() 之前被调用。

    ** ngAfterViewInit() 在第一次检查子指令(或组件)的绑定时调用。因此,它非常适合使用 Angular 2 组件访问和操作 DOM。正如@Günter Zöchbauer 之前提到的那样,@ViewChild() 是正确的,因此在其中运行良好。

    例子:

    @Component({
        selector: 'widget-three',
        template: `<input #input1 type="text">`
    })
    export class WidgetThree{
        @ViewChild('input1') input1;
    
        constructor(private renderer:Renderer){}
    
        ngAfterViewInit(){
            this.renderer.invokeElementMethod(
                this.input1.nativeElement,
                'focus',
                []
            )
        }
    }
    

    【讨论】:

    • 我认为你在这里错了。 ngAfterViewInit() 仅在 ngAfterContentChecked() 之后执行,而 ngAfterContentChecked() 仅在 ngAfterContentInit() 和每个后续 ngDoCheck() 之后执行。请参阅 Angular 生命周期钩子详细信息以获取更多详细信息angular.io/guide/lifecycle-hooks
    猜你喜欢
    • 2018-03-01
    • 2018-02-20
    • 1970-01-01
    • 2018-11-18
    • 2019-08-30
    • 2019-01-10
    • 2017-08-30
    • 2016-04-15
    • 2018-01-06
    相关资源
    最近更新 更多