Як я повинен використовувати нову статичну опцію для @ViewChild у Angular 8?


204

Як я можу налаштувати нову дитину з кутом перегляду 8?

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

проти

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

Який краще? Коли я повинен використовувати static:truevs static:false?

Відповіді:


237

У більшості випадків ви хочете використовувати {static: false}. Встановивши його таким чином, ви знайдете збіги запитів, які залежать від обов'язкової прив'язки (наприклад, структурних директив *ngIf, etc...).

Приклад використання 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;
}

Це static: falseбуде стандартною поведінкою за замовчуванням у куті 9. Детальніше тут і тут

{ static: true }Опція була введена для підтримки створення вбудованих поглядів на льоту. Коли ви створюєте представлення динамічно і хочете отримати доступ до нього TemplateRef, ви не зможете це зробити, ngAfterViewInitоскільки це призведе до ExpressionHasChangedAfterCheckedпомилки. Встановлення статичного прапора в істинне створить ваш погляд у ngOnInit.

Тим не менш:

У більшості інших випадків найкращою практикою є використання {static: false}.

Будьте в курсі, що { static: false }параметр буде встановлений за замовчуванням у куті 9. Це означає, що встановити статичний прапор більше не потрібно, якщо ви не хочете використовувати static: trueпараметр.

Ви можете використовувати команду angular cli ng updateдля автоматичного оновлення поточної бази коду.

Для посібника з міграції та ще більше інформації про це ви можете перевірити тут і тут

Чим відрізняються статичні та динамічні запити?

Статичний параметр для запитів @ViewChild () та @ContentChild () визначає, коли результати запиту стануть доступними.

За допомогою статичних запитів (static: true) запит вирішується, як тільки створений вид, але перед тим, як розпочнеться виявлення змін. Однак результат ніколи не буде оновлюватися, щоб відображати зміни у вашому представленні, наприклад зміни блоків ngIf та ngFor.

За допомогою динамічних запитів (статичні: хибні) запит вирішується після ngAfterViewInit () або ngAfterContentInit () для @ViewChild () та @ContentChild () відповідно. Результат буде оновлений для змін у вашому представленні, таких як зміни блоків ngIf та ngFor.


Оновіть посилання на кутові документи (змінено після випуску) angular.io/api/core/ViewChild#description
Sachin Gupta

2
Я не можу отримати доступ до екземпляра childView. Це говорить, що не визначено весь час.
Несан Мано

Чи можете ви надати посилання на цю інформацію про видалення статичної опції в куті 9?
Олексій Маринов

@AlexMarinov Я оновив свою відповідь, щоб зрозуміти, що буде в куті 9. Посилання про це знаходиться в посібнику з міграції
Poul Kruijt

1
@ MinhNghĩa, якщо ви вкладете весь компонент поза шаблоном компонента, ви можете використовувати його { static: true }, але якщо немає прямої необхідності мати доступ до ViewChild всередині ngOnInit, вам слід просто скористатися { static: false }.
Poul Kruijt

88

Отже, як правило, ви можете перейти до наступного:

  • { static: true }повинен бути встановлений , якщо ви хочете отримати доступ до ViewChildін ngOnInit.

  • { static: false }можна отримати доступ лише в ngAfterViewInit. Це також те, для чого ви хочете піти, коли *ngIfу вашому шаблоні є структурна директива (тобто ).


2
Примітка. У Angular 9 статичний прапор встановлений за замовчуванням на false, тому "будь-які {static: false} прапори можна безпечно видалити". Документація: angular.io/guide/static-query-migration
Stevethemacguy

17

З кутових док

статичний - чи вирішувати результати запиту до запуску виявлення змін (тобто повертати лише статичні результати). Якщо ця опція не передбачена, компілятор повернеться до своєї поведінки за замовчуванням, яка полягає у використанні результатів запитів для визначення часу вирішення запиту. Якщо будь-які результати запиту знаходяться всередині вкладеного перегляду (наприклад, * ngIf), запит буде вирішений після запуску виявлення змін. В іншому випадку це буде вирішено до запуску виявлення змін.

Можливо, краще використовувати ідею, static:trueякщо дитина не залежить від будь-яких умов. Якщо видимість елемента зміниться, то це static:falseможе дати кращі результати.

PS: Оскільки його нова функція, нам може знадобитися запустити орієнтири для продуктивності.

Редагувати

Як зазначає @Massimiliano Sartoretto, github прихильність може дати вам більше розуміння.


3
Я б додав офіційних мотивів за цією функцією github.com/angular/angular/pull/28810
Масміліміано Сарторетто

2

Прийшов сюди, тому що ViewChild був нульовим в ngOnInit після оновлення до Angular 8.

Статичні запити заповнюються перед ngOnInit, тоді як динамічні запити (статичні: помилкові) заповнюються після. Іншими словами, якщо viewchild тепер є нульовим в ngOnInit після встановлення static: false, слід розглянути можливість зміни на static: true або перемістити код на ngAfterViewInit.

Дивіться https://github.com/angular/angular/blob/master/packages/core/src/view/view.ts#L332-L336

Інші відповіді правильні і пояснюють, чому це так: Запити, залежні від структурних директив, наприклад, посилання ViewChild всередині ngIf, повинні запускатися після того, як умовна умова цієї директиви буде усунена, тобто після виявлення змін. Однак можна безпечно використовувати статичну: true та таким чином вирішувати запити перед ngOnInit для немережних посилань. Імхо, саме цей випадок містить згадування як нульовий виняток, можливо, це буде перший спосіб, коли ви зіткнетеся з цією особливістю, як це було для мене.


1

переглянути домен @angular 5+ токена два аргументи ('локальна довідкова назва', статична: хибна | правда)

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

щоб знати різницю між істинним і хибним, перевірте це

статичний - чи вирішувати результати запиту до запуску виявлення змін (тобто повертати лише статичні результати). Якщо ця опція не передбачена, компілятор повернеться до своєї поведінки за замовчуванням, яка полягає у використанні результатів запитів для визначення часу вирішення запиту. Якщо будь-які результати запиту знаходяться всередині вкладеного перегляду (наприклад, * ngIf), запит буде вирішений після запуску виявлення змін. В іншому випадку це буде вирішено до запуску виявлення змін.


0

У ng8 ви можете вручну встановити, коли отримати доступ до дочірнього компонента у батьківському компоненті. Якщо ви встановите static на true, це означає, що батьківський компонент отримує лише визначення компонента в onInitгачку: Наприклад:

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

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

Якщо статична помилка, то ви отримаєте визначення лише в ngAfterViewInit (), в ngOnInit (), ви не визначитеся.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.