Tôi nên sử dụng tùy chọn tĩnh mới cho @ViewChild trong Angular 8 như thế nào?


204

Làm thế nào tôi nên cấu hình con xem Angular 8 mới?

@ViewChild('searchText', {read: ElementRef, static: false})
public searchTextInput: ElementRef;

đấu với

@ViewChild('searchText', {read: ElementRef, static: true})
public searchTextInput: ElementRef;

Cái nào tốt hơn? Khi nào tôi nên sử dụng static:truevs static:false?

Câu trả lời:


237

Trong hầu hết các trường hợp, bạn sẽ muốn sử dụng {static: false}. Đặt nó như thế này sẽ đảm bảo các kết quả truy vấn phụ thuộc vào độ phân giải ràng buộc (như chỉ thị cấu trúc *ngIf, etc...) sẽ được tìm thấy.

Ví dụ về thời điểm sử dụng static: false:

@Component({
  template: `
    <div *ngIf="showMe" #viewMe>Am I here?</div>
    <button (click)="showMe = !showMe"></button>
  ` 
})
export class ExampleComponent {
  @ViewChild('viewMe', { static: false })
  viewMe?: ElementRef<HTMLElement>; 

  showMe = false;
}

Đây static: falsesẽ là hành vi dự phòng mặc định trong Angular 9. Đọc thêm tại đâyđây

Các { static: true }tùy chọn được giới thiệu để hỗ trợ việc tạo ra lượt xem được nhúng một cách nhanh chóng. Khi bạn đang tạo một chế độ xem một cách linh hoạt và muốn xác nhận TemplateRef, bạn sẽ không thể làm như vậy vì ngAfterViewInitnó sẽ gây ra ExpressionHasChangedAfterCheckedlỗi. Đặt cờ tĩnh thành true sẽ tạo chế độ xem của bạn trong ngOnInit.

Tuy nhiên:

Trong hầu hết các trường hợp khác, thực hành tốt nhất là sử dụng {static: false}.

Mặc dù vậy, hãy lưu ý rằng { static: false }tùy chọn sẽ được đặt mặc định trong Angular 9. Điều đó có nghĩa là việc đặt cờ tĩnh không còn cần thiết nữa, trừ khi bạn muốn sử dụng static: truetùy chọn.

Bạn có thể sử dụng ng updatelệnh cli góc để tự động nâng cấp cơ sở mã hiện tại của bạn.

Để biết hướng dẫn di chuyển và thậm chí nhiều thông tin hơn về điều này, bạn có thể kiểm tra tại đâyđây

Sự khác biệt giữa các truy vấn tĩnh và động là gì?

Tùy chọn tĩnh cho các truy vấn @ViewChild () và @ContentChild () xác định khi kết quả truy vấn có sẵn.

Với các truy vấn tĩnh (static: true), truy vấn sẽ giải quyết khi chế độ xem được tạo, nhưng trước khi phát hiện thay đổi chạy. Tuy nhiên, kết quả sẽ không bao giờ được cập nhật để phản ánh các thay đổi đối với chế độ xem của bạn, chẳng hạn như thay đổi đối với các khối ng If và ngFor.

Với các truy vấn động (static: false), truy vấn sẽ giải quyết sau ngAfterViewInit () hoặc ngAfterContentInit () cho @ViewChild () và @ContentChild (). Kết quả sẽ được cập nhật để thay đổi chế độ xem của bạn, chẳng hạn như thay đổi đối với các khối ng If và ngFor.


Vui lòng cập nhật liên kết cho các tài liệu góc (đã thay đổi sau khi phát hành) angular.io/api/core/ViewChild#description
Sachin Gupta

2
Tôi không thể truy cập thể hiện của childView. Nó nói không xác định tất cả các thời gian.
Nesan Mano

Bạn có thể vui lòng cung cấp một liên kết về thông tin đó để loại bỏ tùy chọn tĩnh trong Angular 9 không?
Alex Marinov

@AlexMarinov Tôi đã cập nhật câu trả lời của mình để làm rõ hơn những gì sẽ xảy ra trong góc 9. Liên kết về điều này nằm trong hướng dẫn di chuyển
Poul Kruijt

1
@ MinhNghĩa nếu bạn lồng toàn bộ thành phần bên ngoài mẫu của thành phần, bạn có thể sử dụng { static: true }, nhưng nếu không có nhu cầu trực tiếp để có quyền truy cập vào ViewChild bên trong ngOnInit, bạn chỉ nên sử dụng { static: false }.
Poul Kruijt

88

Vì vậy, như một quy tắc của ngón tay cái, bạn có thể đi như sau:

  • { static: true }cần phải được đặt khi bạn muốn truy cập ViewChildvào ngOnInit.

  • { static: false }chỉ có thể được truy cập trong ngAfterViewInit. Đây cũng là những gì bạn muốn thực hiện khi bạn có một chỉ thị cấu trúc (tức là *ngIf) trên phần tử của bạn trong mẫu của bạn.


2
Lưu ý: Trong Angular 9, cờ tĩnh mặc định là false, do đó "mọi cờ {static: false} có thể được gỡ bỏ an toàn". Tài liệu: angular.io/guide/static-query-migration
Stevethemacguy

17

Từ các tài liệu góc

tĩnh - có hay không giải quyết kết quả truy vấn trước khi phát hiện thay đổi chạy (tức là chỉ trả về kết quả tĩnh). Nếu tùy chọn này không được cung cấp, trình biên dịch sẽ quay trở lại hành vi mặc định của nó, đó là sử dụng kết quả truy vấn để xác định thời gian giải quyết truy vấn. Nếu bất kỳ kết quả truy vấn nào nằm trong chế độ xem lồng nhau (ví dụ: * ng If), truy vấn sẽ được giải quyết sau khi phát hiện thay đổi chạy. Nếu không, nó sẽ được giải quyết trước khi phát hiện thay đổi.

Nó có thể là một ý tưởng tốt hơn để sử dụng static:truenếu đứa trẻ không phụ thuộc vào bất kỳ điều kiện. Nếu khả năng hiển thị của phần tử thay đổi, thì static:falsecó thể cho kết quả tốt hơn.

PS: Vì đây là một tính năng mới, chúng tôi có thể cần chạy điểm chuẩn cho hiệu suất.

Biên tập

Như được đề cập bởi @Massimiliano Sartoretto, cam kết github có thể cung cấp cho bạn thông tin chi tiết hơn.


3
Tôi sẽ thêm các động lực chính thức đằng sau tính năng này github.com/angular/angular/pull/28810
Massimiliano Sartoretto

2

Đến đây vì ViewChild không có giá trị trong ngOnInit sau khi nâng cấp lên Angular 8.

Các truy vấn tĩnh được điền trước ngOnInit, trong khi các truy vấn động (tĩnh: false) được điền sau. Nói cách khác, nếu một viewchild bây giờ là null trong ngOnInit sau khi bạn đặt static: false, bạn nên xem xét việc thay đổi thành static: true hoặc chuyển mã sang ngAfterViewInit.

Xem https://github.com/angular/angular/blob/master/packages/core/src/view/view.ts#L332-L336

Các câu trả lời khác là chính xác và giải thích tại sao lại như vậy: Các truy vấn phụ thuộc vào các chỉ thị cấu trúc, ví dụ: tham chiếu ViewChild bên trong ngNếu, nên chạy sau khi điều kiện của lệnh này được giải quyết, tức là sau khi phát hiện thay đổi. Tuy nhiên, người ta có thể sử dụng tĩnh: true và do đó giải quyết các truy vấn trước ngOnInit cho các tham chiếu không được kiểm tra. Imho trường hợp cụ thể này được đề cập như một ngoại lệ null có thể là cách đầu tiên bạn sẽ gặp phải tính đặc biệt này, như nó là dành cho tôi.


1

xem con @angular 5+ mã thông báo hai đối số ('tên tham chiếu cục bộ', static: false | true)

@ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;

để biết sự khác biệt giữa đúng và sai kiểm tra điều này

tĩnh - có hay không giải quyết kết quả truy vấn trước khi phát hiện thay đổi chạy (tức là chỉ trả về kết quả tĩnh). Nếu tùy chọn này không được cung cấp, trình biên dịch sẽ quay trở lại hành vi mặc định của nó, đó là sử dụng kết quả truy vấn để xác định thời gian giải quyết truy vấn. Nếu bất kỳ kết quả truy vấn nào nằm trong chế độ xem lồng nhau (ví dụ: * ng If), truy vấn sẽ được giải quyết sau khi phát hiện thay đổi chạy. Nếu không, nó sẽ được giải quyết trước khi phát hiện thay đổi.


0

Trong ng8, bạn có thể đặt thủ công khi truy cập thành phần con trong thành phần cha. Khi bạn đặt tĩnh thành true, điều đó có nghĩa là thành phần cha mẹ chỉ nhận được định nghĩa của thành phần trong onInithook: Eg:

 // You got a childComponent which has a ngIf/for tag
ngOnInit(){
  console.log(this.childComponent);
}

ngAfterViewInit(){
  console.log(this.childComponent);
}

Nếu tĩnh là sai, thì bạn chỉ nhận được định nghĩa trong ngAfterViewInit (), trong ngOnInit (), bạn sẽ không xác định được.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.