Angular: прослушивание модели с измененной стратегией обнаружения.OnPush

#angular #rxjs #angular2-changedetection

#angular #rxjs #angular2-измененное обнаружение

Вопрос:

Допустим, у меня есть одна большая модель Json, которую мой сервер отправляет моему интерфейсу, которая будет выглядеть следующим образом:

 {
     dataA: { //some object },
     dataB: { //some object },
     dataC: { //some object },
     ...
}
  

Теперь допустим, у меня есть компонент, который принимает dataA как @Input() , компонент B, который принимает dataB как @Input() и т. Д:

 @Component({
    selector: 'comp-a'
})
class ComponentA {
    @Input() _dataA;
}

@Component({
    selector: 'comp-b'
})
class ComponentA {
    @Input() _dataB;
}

// .... other components

@Component({
    selector: 'app',
    template:`
        <comp-a [_dataA]="dataA"></comp-a>
        <comp-b [_dataB]="dataB"></comp-b>
        ...
    `
})
class AppComponent {
}
  

И что я хочу заставить эти компоненты использовать стратегию обнаружения изменений OnPush.

При получении новой модели может случиться так, что поле данных в модели не изменилось по сравнению с его предыдущим значением в предыдущей модели, поэтому я бы не хотел, чтобы они снова передавались как @Input() компоненту, чтобы избежать запуска обнаружения изменений впустую.

Есть ли какой-нибудь умный способ обнаружить изменения в моей модели на интерфейсной стороне, прежде чем передавать ее данные как @Input() моим компонентам, и уведомлять их только тогда, когда их соответствующие данные изменились? Или я должен позволить Angular выполнять само обнаружение изменений? Действительно ли OnPush здесь уместен?

Ответ №1:

OnPush повышает эффективность, поскольку не проверяет свойства модели и запускает обновление при изменении экземпляра объекта, а не свойств объекта. Для выполнения того, что вы предлагаете, потребуется проверить свойства вашего объекта, чтобы увидеть, изменилось ли что-нибудь. По сути, вы бы заново изобрели обнаружение изменений, поэтому я не вижу в этом смысла, и вам нужно было бы сделать это лучше, чем это сделала команда Angular, чтобы увидеть какую-либо выгоду.

Вы также отметили этот вопрос с помощью rxjs, но в вопросе ничего нет о rxjs. Лучший способ реализовать обнаружение изменений OnPush — это использовать rxjs observables и использовать асинхронный канал в вашем шаблоне. Таким образом, вы получаете только наблюдаемое, которое выдает обновленное значение.

 @Component({
    selector: 'app',
    template:`
        <comp-a [_dataA]="dataA$ | async"></comp-a>
        <comp-b [_dataB]="dataB$ | async"></comp-b>
        ...
    `
})
class AppComponent {
    dataA$ = new BehaviorSubject<DataAModel>(undefined);
    dataB$ = new BehaviorSubject<DataBModel>(undefined);

    updateA() {
      if (a has changed) { // If your detection to check changes is inefficient then there is no point
        this.dataA$.next(a);
      }
    }

    updateB() {
      if (b has changed) {
        this.dataB$.next(b);
      }
    }
}