Angular 5 - как ограничить обнаружение изменений только областью компонента?

Как настроить компонент Angular так, чтобы обнаружение изменений не запускалось для всего приложения, а только для самого компонента и его дочерних элементов?

Рабочий пример: https://stackblitz.com/edit/angular-irc-starter-4txpbu?file=app%2Ftimer%2Ftimer.component.ts

Есть счетчик, увеличивающий значение на единицу каждую секунду. Это TimerComponent, и он работает по назначению - значение увеличивается и обновляется каждую секунду.

@Component({
  selector: 'app-timer',
  template: `{{value}}`
})
export class TimerComponent implements OnInit {
  value: number = 0;
  ngOnInit() {
    setInterval(() => this.value++, 1000);
  }
}

Однако посмотрите на родительский компонент AppComponent.

<h3>Internal timer:</h3>
<p>Should not perform change detection for the whole app</p>
<app-timer></app-timer>

<h3>External binding</h3>
<p>Should not be updated after timer changes</p>
<p>{{someBindingProperty}}</p>

someBindingProperty - получатель:

get someBindingProperty() {
  this.bindingTimer++;
  return this.bindingTimer;
}

Проблема: когда TimerComponent увеличивает значение, обнаружение изменений срабатывает для всего приложения. Можно ли активировать обнаружение изменений только в компоненте и дочерних элементах?

Примечание: если я добавлю к TimerComponent:

changeDetection: ChangeDetectionStrategy.OnPush

Тогда изменения не обнаруживаются в этом компоненте, но обнаружение изменений по-прежнему запускается для всего приложения. Так что это не выход.


person Politechniczny    schedule 19.12.2018    source источник
comment
какая-то конкретная причина, по которой вы хотите это сделать? пренебрежение родительской грязной проверкой может привести к тому, что ваше представление находится в несогласованном состоянии ... Если вы видите, что состояние зависит от грязной проверки, это сигнал, что ваш код может быть неправильным   -  person ABOS    schedule 19.12.2018
comment
это может сработать, несмотря на некоторые ошибки с консоли (я добавляю кнопку для демонстрации, ее все еще можно изменить) stackblitz.com/edit/angular-irc-starter-6fsui9   -  person ABOS    schedule 19.12.2018
comment
@ABOS: чтобы избежать накладных расходов, вызванных таймером обратного отсчета. Если мы обновляем только внутреннее состояние таймера и нет зависимостей между состоянием таймера и внешним состоянием приложения, нет необходимости обновлять все приложение. Однако, когда мы хотим генерировать некоторые события снаружи, это все еще возможно, повторно войдя в зону Angular: stackblitz.com/edit/   -  person Politechniczny    schedule 21.12.2018
comment
К сожалению, NgZone.run () повторно включает Angular зону для обратного вызова всего интервала.   -  person Politechniczny    schedule 21.12.2018


Ответы (1)


Другой вариант временного отключения обнаружения изменений ChangeDetectorRef

enabled = true;  
constructor(private ref: ChangeDetectorRef)

toggleChangeDetection() {
  if (this.enabled) 
  {
    this.enabled = false;
    this.ref.detach();
  }
  else {
    this.enabled = true;
    this.ref.reattach();
}
person parag badala    schedule 20.12.2018
comment
Кажется, что все состояние приложения по-прежнему обновляется каждую секунду, несмотря на отключение детектора изменений: stackblitz.com/edit/angular-irc-starter-ixapkf?file=app/timer/ - person Politechniczny; 21.12.2018