Как мне использовать новую статическую опцию для @ViewChild в Angular 8?

Как настроить новый дочерний элемент Angular 8?

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

против

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

Что лучше? Когда я должен использовать static:true против static:false?

10 ответов

Решение

В большинстве случаев вы захотите использовать {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 является резервным поведением по умолчанию. Узнайте больше здесь и здесь

{ static: true } Опция была введена для поддержки создания встроенных представлений на лету. Когда вы создаете представление динамически и хотите получить доступ к TemplateRefвы не сможете сделать это в ngAfterViewInit как это вызовет ExpressionHasChangedAfterChecked ошибка. Установка статического флага в true создаст ваше представление в ngOnInit.

тем не менее:

В большинстве других случаев наилучшей практикой является использование {static: false},

Имейте в виду, что статическая опция будет снова удалена в Angular 9. Вы можете использовать угловой ng update Команда для автоматического обновления вашей текущей кодовой базы.

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

Так что, как правило, вы можете пойти на следующее:

  • { static: true } должен быть установлен, когда вы хотите получить доступ к ViewChild в ngOnInit,

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

статическое свойство информирует angular о доступности нашего дочернего элемента

Например: если для static установлено значение true , мы информируем angular, что наш дочерний элемент доступен на странице с самого начала (это означает, что он не зависит от *ngIf, привязок страниц, вызовов API и т. д.), поэтому angular ищет его в самом начале жизненного цикла. ловушка ( ngOnInit) и больше никогда ее не ищет

Если мы устанавливаем для static значение false, мы информируем angular о том, что наш дочерний элемент зависит от некоторых условных директив, поэтому angular пытается искать нашего дочернего элемента после каждого цикла обнаружения изменений, и если он доступен, мы можем получить к нему доступ в хуке жизненного цикла ngAfterViewInit()

Из угловых документов

статический - разрешать или не разрешать результаты запроса перед выполнением обнаружения изменений (т.е. возвращать только статические результаты). Если эта опция не указана, компилятор вернется к своему поведению по умолчанию, которое будет использовать результаты запроса для определения времени разрешения запроса. Если какие-либо результаты запроса находятся во вложенном представлении (например, *ngIf), запрос будет разрешен после выполнения обнаружения изменений. В противном случае оно будет разрешено до запуска обнаружения изменений.

Это может быть лучше использовать static:true если ребенок не зависит ни от каких условий. Если видимость элемента меняется, то static:false может дать лучшие результаты.

PS: Поскольку это новая функция, нам может потребоваться запустить тесты производительности.

редактировать

Как упомянул @Massimiliano Sartoretto, коммит github может дать вам больше идей.

Пришел сюда, потому что 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, должны выполняться после того, как условие этой директивы выполнено, то есть после обнаружения изменения. Однако можно смело использовать static: true и, таким образом, разрешать запросы перед ngOnInit для неопубликованных ссылок. Имхо, этот конкретный случай должен упоминаться как нулевое исключение, вероятно, будет первым способом, с которым вы столкнетесь с этой особенностью, как это было для меня.

В ng8 вы можете вручную установить, когда обращаться к дочернему компоненту в родительском компоненте. Когда вы устанавливаете static в true, это означает, что родительский компонент получает только определение компонента вonInit крючок: Например:

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

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

Если static равно false, тогда вы получите определение только в ngAfterViewInit(), в ngOnInit() вы получите undefined.

Просмотр ребенка

... Можно использовать его для справки по элементам шаблона.

... за пределами ссылки на конкретный компонент.

С синтаксисом в стиле декоратора.@ViewChild( selector) reference : ElementRef || QueryList.

Ссылка на конкретный компонент или элемент.

Используйте это в AfterViewInIt().

Мы могли бы использовать это в Oninit().

Но это для конкретного использования ngAfterViewInit().

Наконец {static : false} должен быть помещен в @ViewChild( Useme , { static : false})... для ссылки на переменную шаблона.

Переменная в файле шаблона выглядит так.#Useme.

Просмотреть дочерний элемент @angular 5+ с двумя аргументами ('локальное ссылочное имя',static: false|true)

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

чтобы узнать разницу между истиной и ложью, проверьте это

static - разрешать или нет результаты запроса перед запуском обнаружения изменений (т.е. возвращать только статические результаты). Если эта опция не указана, компилятор вернется к своему поведению по умолчанию, а именно к использованию результатов запроса для определения времени разрешения запроса. Если какие-либо результаты запроса находятся во вложенном представлении (например, *ngIf), запрос будет разрешен после запуска обнаружения изменений. В противном случае он будет разрешен до запуска обнаружения изменений.

если мы объявим static: true, вначале он будет отображаться только один раз. в противном случае, если мы объявим static: false, это означает, что мы визуализируем его динамически, поэтому всякий раз, когда происходят изменения, он будет отображаться снова и снова. Безопасно объявлять static: false большую часть времени

Для Angular 8 и выше вам нужно использовать решение ниже.

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

Перед внедрением необходимо понять важные вещи

      { static: true } needs to be set when you want to access the ViewChild in ngOnInit.
    
{ static: false } can only be accessed in ngAfterViewInit. This is also what you want to go for when you have a structural directive (i.e. *ngIf) on your element in your template.
Другие вопросы по тегам