Angular2的ngOnInit和ngAfterViewInit有什么区别?


78

我无法理解ngOnInit和之间的区别ngAfterViewInit

我发现它们之间的唯一区别是@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'));
  }
}

Answers:


90

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

ngAfterViewInit()在最初呈现视图之后调用。这就是为什么要@ViewChild()依赖它。渲染视图成员之前,您无法对其进行访问。


当您说渲染时,您是说它出现在屏幕上了吗?(或发送使其呈现在屏幕上)
Royi Namir

2
将其添加到DOM时。如果设置,display: hidden它将一直渲染,但在屏幕上不可见。但是,如果您使用浏览器devtools对DOM进行调查,您将能够看到标记。
君特Zöchbauer

3
您不能在呈现视图成员之前访问它们”-那么您如何解释ViewChild(vc)在上可用onNgInitplnkr.co/edit/AzhRe6bjnuPLKJWEJGwp?p=preview,您能解释一下吗?
罗伊·纳米尔

5
@Royi我无法在手机上打开您的Plunker,它将花费几天时间,直到我返回计算机。静态添加的元素已在中提供ngOnInit。如果您有被渲染为examply内容*ngFor从数据传输给一个@Input,这个内容将尚未在可用ngOnInit
君特Zöchbauer

2
非常感谢您的答复。正是这种情况。所以我想就是这样。i.imgur.com/Vbajl4F.jpg。享受你的假期。
罗伊·纳米尔

25

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

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


1

内容是作为孩子传递的。视图是当前组件的模板。

该视图在内容之前被初始化,ngAfterViewInit()因此被称为before ngAfterContentInit()

ngAfterViewInit()第一次检查子代指令(或组件)的绑定时,将调用** 。因此,它非常适合通过Angular 2组件访问和操作DOM。正如前面提到的@GünterZö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.io/guide/lifecycle-hooks
Suneet Bansal
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.