Насколько я знаю, Angular обновляет только вид, если вы меняете данные в «Angular zone».Асинхронный вызов в вашем примере не подходит для этого.Но если вы хотите, вы можете поместить его в угловую зону или использовать rxjs или извлечь часть кода в новый компонент для решения этой проблемы.Я объясню все:
1 Угловая зона
Наиболее распространенным использованием этого сервиса является оптимизация производительности при запуске работы, состоящей из одного или нескольких асинхронныхзадачи, которые не требуют обновлений пользовательского интерфейса или обработки ошибок для обработки Angular.Такие задачи могут быть запущены с помощью runOutsideAngular, и при необходимости эти задачи могут повторно войти в угловую зону с помощью run .https://angular.io/api/core/NgZone
Ключевая часть - это функция запуска.Вы можете внедрить NgZone и поместить свое обновление значения в обратный вызов run объекта NgZone:
constructor(private ngZone: NgZone ) { }
testVariable: string;
ngOnInit() {
this.testVariable = 'foo';
this.someService.someObservable.subscribe(
() => console.log('success'),
(error) => console.log('error', error),
() => {
this.ngZone.run( () => {
this.testVariable += '-bar';
});
}
);
}
Согласно этому ответу, это приведет к тому, что все приложение обнаружит изменения, тогда как вашПодход ChangeDetectorRef.detectChanges обнаружил бы изменения только в вашем компоненте и его потомках.
2 RxJS
Другим способом было бы использовать rxjs
для обновления представления.Когда вы впервые подписываетесь на ReplaySubject , это даст вам последнее значение.A BehaviorSubject в основном то же самое, но позволяет вам определить значение по умолчанию (имеет смысл в вашем примере, но не обязательно всегда будет правильным выбором).После этого начального излучения это обычный субъект воспроизведения:
this.testVariable = 'foo';
testEmitter$ = new BehaviorSubject<string>(this.testVariable);
ngOnInit() {
this.someService.someObservable.subscribe(
() => console.log('success'),
(error) => console.log('error', error),
() => {
this.testVariable += '-bar';
this.testEmitter.next(this.testVariable);
}
);
}
По вашему мнению, вы можете подписаться на тему, используя async pipe:
{{testEmitter$ | async}}
3 Извлечение кода в новый компонент
Если вы отправите строку в другой компонент, она также будет обновлена.Вы должны будете использовать селектор @Input()
в новом компоненте.
Таким образом, новый компонент имеет следующий код:
@Input() testVariable = '';
И переменная testVariable назначается в HTML, как и раньше, с фигурными скобками.
В родительском представлении HTML вы можете затем передать переменную элемента parentelement дочернему элементу:
<app-child [testVariable]="testVariable"></app-child>
Таким образом, вы находитесь в угловой зоне.
4 Личные предпочтения
Мое личное предпочтение - использовать rxjs или компонентный способ.Использование Detechanges или NGZone кажется мне более хакерским.