Реактивный контроль формы запускает обнаружение изменений

Реактивный элемент FormControl запускает ChangeDetection всякий раз, когда изменяется входное значение. Я добавил стратегию OnPush, но все равно работает ChangeDetection,

@Component({
  selector: 'app-server-input',
  templateUrl: './server-input.component.html',
  styleUrls: ['./server-input.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})

Директива FormControl запускает ChangeDetection. Как остановить запуск ChangeDetection при изменении ввода?

serverName: FormControl = new FormControl();

Вот мой код на StackBlitz.

Примечание. Здесь следует отметить одну вещь: если вы нажимаете кнопку, вызывается ngDocheck, поэтому я использовал диспетчер событий, чтобы остановить обнаружение изменений.


person anonymous    schedule 07.04.2021    source источник
comment
Похоже, что внутренняя реализация запускает обнаружение изменений OnPush. На этом этапе было бы лучше изменить то, как вы пытаетесь реализовать свое решение.   -  person Trevor Kropp    schedule 12.04.2021
comment
indepth.dev/posts/1131/   -  person Robin Dijkhof    schedule 12.04.2021
comment
Пожалуйста, прочтите статью, @Robin Dijkhof — правильный ответ: прочитайте эту статью" rel="nofollow noreferrer">indepth.dev/posts/1131/   -  person Luis Limas    schedule 13.04.2021
comment
Вы должны понимать, что если fomcontrol не назначен, то нет и обнаружения изменений.   -  person anonymous    schedule 15.04.2021


Ответы (4)


ngDoCheck работает всегда. Независимо от того, какую стратегию вы используете. См. https://indepth.dev/posts/1131/if-you-think-ngdocheck-means-your-component-is-being-checked-read-this-article и Зачем нам нужен `ngDoCheck`

Я не вижу никакой причины, по которой вы хотели бы знать, когда и как было запущено обнаружение изменений. Если вы хотите что-то сделать при изменении, просто используйте сеттер для ввода:

_name: string;
get name(): string{
    return this._name;
}
@Input() set name(value: string) {
    this._name = value;
    this.doUpdateSomething();
}
person Robin Dijkhof    schedule 12.04.2021
comment
Я добавил кнопку в родительский компонент и щелкнул ее, затем ngDocheck запустился в дочернем компоненте, но когда я обработал событие щелчка вне ngZone, nDocheck дочернего компонента не запустился. Этот эксперимент доказывает, что ngDoCheck не всегда запускается по умолчанию. - person anonymous; 12.04.2021
comment
Вы должны понимать, что когда не назначен элемент управления формой, тогда ngDocheck не запускается в дочернем компоненте. - person anonymous; 15.04.2021

Я разветвил и обновил ваш код: https://stackblitz.com/edit/child-component-2bstm4?file=app/app.component.ts

  ngOnInit() {    
    this.zone.runOutsideAngular(() => (
      this.serverName = new FormControl(),
      this.cd.detach()
      )
    );
  }
person Lonely    schedule 18.04.2021
comment
В отличие от разработчиков TypeScript, разработчики Angular также думали о том, что произойдет, если мы подожжем и отключим пожарную сигнализацию. Если вы посмотрите на API ChangeDetectorRef, вы обнаружите, что они продумали все возможности. Detach — один из них: angular.io/api/core/ChangeDetectorRef . Все эти шаги можно инициировать вручную, что в лучшем случае должно работать автоматически. - person Lonely; 18.04.2021
comment
Я присуждаю награду за этот ответ. Но это не сработало в моем приложении. - person anonymous; 18.04.2021
comment
StackBlitz работает с зонами, где в качестве параметра указано this.cd.detach(). В вашем реальном приложении вы должны разместить его перед созданием формы. - person Lonely; 18.04.2021
comment
вот мой stackblitz -› stackblitz.com/edit/ - person anonymous; 18.04.2021
comment
Я уже пробовал с cd.detach, не работает. - person anonymous; 18.04.2021
comment
Вы намеренно использовали this.cdr.detectChanges(); ? - person Lonely; 18.04.2021
comment
Да, потому что этот компонент отображения имеет стратегию on-push, и когда наблюдаемый испускает, я должен вызвать метод обнаружения изменений - person anonymous; 18.04.2021
comment
Я боюсь, что после того, как все будет работать асинхронно, они будут мешать друг другу. Вы должны реорганизовать рабочий процесс в своем приложении. Я всегда использую async-await, чтобы быть уверенным в порядке выполнения. - person Lonely; 18.04.2021

Чтобы angular не запускал обнаружение изменений каждый раз, когда пользователь взаимодействует с полем ввода, вы должны отключить детектор изменений. Вам нужно внедрить ChangeDetectorRef и вызвать его метод detach.

  constructor(private cd: ChangeDetectorRef) {}
  ngOnInit() {
    this.cd.detach();
  }

Обнаружение изменений больше не будет выполняться автоматически для этого компонента и его дочерних элементов. Когда вам нужно инициировать обнаружение изменений, вы можете вызвать методDetectChanges для ChangeDetectorRef.

Например, это будет запускать обнаружение изменений каждые 5 секунд.

  ngOnInit() {
    this.cd.detach();
    setInterval(() => this.cd.detectChanges(), 5000);
  }
person J.Loscos    schedule 12.04.2021
comment
Это вообще не актуально. - person anonymous; 13.04.2021

В ссылке, указанной ниже, есть возможность отключить обнаружение изменений в контроле формы.

отключить управление формой

person Tejas Mahajan    schedule 18.04.2021