2016-11-26 19 views
10

Tôi không thể hiểu sự khác biệt giữa ngOnInitngAfterViewInit.Sự khác nhau giữa ngOnInit và ngAfterViewInit của Angular2 là gì?

Tôi thấy sự khác biệt duy nhất giữa chúng là @ViewChild. Theo các mã sau, các elementRef.nativeElement trong họ là như nhau.

Cảnh nào chúng ta nên sử dụng 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')); 
    } 
} 

Trả lời

8

ngOnInit() được gọi ngay sau khi các thuộc tính dữ liệu ràng buộc của chỉ thị đã được kiểm tra lần đầu tiên, và trước khi bất cứ đứa con của nó đã được kiểm tra. Nó được gọi chỉ một lần khi chỉ thị được khởi tạo.

ngAfterViewInit() được gọi sau chế độ xem của thành phần và chế độ xem của trẻ em, được tạo. Một móc vòng đời của nó được gọi sau khi xem thành phần đã được khởi tạo đầy đủ.

16

ngOnInit() được gọi sau ngOnChanges() được gọi là lần đầu tiên. ngOnChanges() được gọi là mỗi lần đầu vào được cập nhật bằng cách phát hiện thay đổi.

ngAfterViewInit() được gọi sau khi chế độ xem được hiển thị ban đầu. Đây là lý do tại sao @ViewChild() phụ thuộc vào nó. Bạn không thể truy cập thành viên xem trước khi họ được hiển thị.

+0

Khi bạn nói _rendered_, làm bạn có nghĩa là nó sẽ xuất hiện trên màn hình? (hoặc được gửi để hiển thị trên màn hình) –

+2

Khi được thêm vào DOM. Nếu bạn đặt 'display: hidden' cho đến khi hiển thị, nhưng không hiển thị trên màn hình. Nhưng nếu bạn điều tra DOM bằng cách sử dụng trình khám phá của trình duyệt, bạn sẽ có thể thấy đánh dấu. –

+1

"_bạn không thể truy cập thành viên xem trước khi chúng được hiển thị_" - Vậy làm cách nào bạn giải thích rằng 'ViewChild' (vc) có sẵn trên' onNgInit'? https://plnkr.co/edit/AzhRe6bjnuPLKJWEJGwp?p=preview, Bạn có thể giải thích? –

0

Nội dung là nội dung được truyền như trẻ em. Xem là mẫu của thành phần hiện tại.

Chế độ xem được khởi tạo trước nội dung và trước đó ngAfterViewInit() được gọi trước ngAfterContentInit().

** ngAfterViewInit() được gọi khi các liên kết của chỉ thị trẻ em (hoặc thành phần) đã được kiểm tra lần đầu tiên. Do đó nó hoàn hảo cho việc truy cập và thao tác DOM với các thành phần Angular 2. Như @ Günter Zöchbauer đã đề cập trước đây là chính xác @ViewChild() do đó chạy tốt bên trong nó.

Ví dụ:

@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', 
      [] 
     ) 
    } 
} 
Các vấn đề liên quan