#angular #typescript #loops #angular6 #angular-changedetection
#angular #typescript #циклы #angular6 #angular-changedetection
Вопрос:
Похоже, использование геттеров внутри шаблонов приводит к тому, что обнаружение угловых изменений переходит в цикл (геттер вызывается сотни раз). Прочитав тонну статей по подобным вопросам, я, похоже, не могу получить четкого ответа.
Справочная информация:
Я действительно считаю, что использование геттеров внутри шаблона — это самый чистый подход с точки зрения удобства обслуживания, однако, по-видимому, из-за того, что Angular не может знать, изменилось ли значение getter, пока не вызовет его, он просто вызывает его все время. Я пока нашел три альтернативы:
- Прекратите использование геттеров, сделайте все свойства общедоступными и получите к ним прямой доступ
- Сохраните значение каждого геттера в общедоступном свойстве компонента и привяжите его вместо геттера в шаблоне
- Измените режим обнаружения изменений в Angular с default на OnPush
Вариант 1 может показаться нелогичным по сравнению с преимуществами использования классов Typescript. Вариант 2 может показаться ненужным дублированием кода и снизить удобство сопровождения, вариант 3 потребует значительного рефакторинга.
Вот пример (упрощенный для иллюстративных целей)
Модель:
export class UserModel {
private id: string;
get getId() {
console.log('Getting id');
return this.id;
}
set setId(id) {
this.id = id;
}
constructor() {
}
}
Component.html
<h1>Test</h1>
<p>{{user.getId}}</p>
Component.ts
import {Component, OnInit} from '@angular/core';
import {TestModel} from './test.model';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
public user: UserModel;
ngOnDestroy() {
if (this.userObserver) { this.userObserver.unsubscribe(); }
}
ngOnInit() {
this.userObserver = this.userObservable.subscribe(
(data: UserModel) => {
this.user = data;
},
(err: any) => {
console.error(err);
});
}
}
Выведет следующий консольный журнал:
консоль.вывод журнала
Кто-нибудь может порекомендовать наилучшую практику, позволяющую избежать ненужных циклов при работе со сложными моделями в Angular? Или даже правильный способ отладки такого типа поведения, в том виде, в каком он есть сейчас, I am console.регистрирует методы получения и отслеживает всплески использования memmory.
РЕДАКТИРОВАТЬ (Ответ) После более продолжительного исследования, копания в трассировках стека, я обнаружил, что бесконечный цикл обнаружения изменений на самом деле был вызван внедренной нами службой под названием ‘Sentry’. По-видимому, это вызывает проблему при запуске консоли.используется журнал, который запускает обнаружение изменений. Нашел проблему github по этому поводу здесь:github.com/getsentry/sentry-javascript/issues/1883 Не нашел решения (кажется, по своей сути несовместимым), обновится, если я найду для этого исправление.
Комментарии:
1. Используете ли вы геттеры или нет, ничего не меняет: Angular по-прежнему необходимо обнаруживать изменения, и, следовательно, ему по-прежнему необходимо оценивать выражения. Использование геттера позволяет вам заметить, потому что вы можете добавить состояние ведения журнала, в то время как вы не замечаете его при использовании полей из-за отсутствия операторов ведения журнала. Но независимо от того, используете вы геттер или нет, произойдет одинаковое количество обнаружений изменений и вычислений выражений.
2. В качестве дополнительного примечания: получатель и установщик должны иметь одно и то же имя (название свойства). Например:
get id() { return this._id; } set id(value) { this._id = value; }
.3. @JBNizet, спасибо за подтверждение этого, получилось довольно запутанно, поскольку в нескольких комментариях к переполнению стека упоминалось, что использование методов может вызвать это. После более продолжительного исследования, копаясь в трассировках стека, я обнаружил, что бесконечный цикл обнаружения изменений на самом деле был вызван внедренной нами службой под названием «Sentry». По-видимому, это вызывает проблему при запуске консоли. используется журнал, который запускает обнаружение изменений. Нашел проблему github по этому поводу здесь: github.com/getsentry/sentry-javascript/issues/1883 Не нашел решения (кажется, по своей сути несовместимым), обновится, если я найду для этого исправление.
4. @d_stack обнаружил это с помощью
@sentry/browser@5.19.2
в Angular 8.2.7. не могли бы вы обновить фактический ответ тем, что, по вашему мнению, было лучшим решением цикла обнаружения изменений?
Ответ №1:
Использовать ChangeDetectionStrategy.onPush
Выполните следующую команду, чтобы установить это значение по умолчанию для вашего проекта при создании новых компонентов через CLI.
ng config schematics.@schematics/angular.component.changeDetection OnPush
Вообще говоря, старайтесь избегать сложных методов получения или вызова функций из шаблона. Если вам нужно преобразовать данные, рассмотрите возможность использования каналов, которые запоминаются.