angular - Angular 应用程序中的声明式和反应式方法之间的摩擦
问题描述
这是我定期面临的一个问题,当我的应用程序由声明性组件组成时(因此它们的模板完全可以通过其属性的值来预测),但在某些时候,有一个主题以一种反应性的方式推送一个新值。
假设我有这样的东西:基于数组元素的组件列表。
<hello *ngFor="let h of helloComponents"></hello>
hello 组件从服务订阅了 BehaviorSubject。
在某些时候(例如,当单击按钮时),behaviourSubject 会发出一个新值,但数组也会更新。
事件顺序如下:
- 主题发出一个新值
- 订阅主题的组件接收新值
- 数组被更新,新组件被初始化,它们从主题接收新值作为第一个值
问题是旧组件在销毁之前收到了值,因此它们可能会运行我不希望它们执行的代码,因为它们在第 3 点被销毁。
如果我首先更新数组,然后从主题中推送一个新值,那么场景不会改变。
我找到了 2 个修复:
A. 使用 setTimeout 确保在旧组件已被 Angular Change Detection 销毁时主体发出新值。但我不知道这个解决方案有多强大......
this.myarray= [4, 5];
setTimeout(() => subject.next(new value));
B.使用observeOn(asyncScheduler)
this.stateService.state$.pipe(
observeOn(asyncScheduler)
).subscribe(
state => console.log(`helloComponent ${this.id}, state: ${state}`)
)
但我真的是 Rxjs 调度程序的新手,我不知道这是一个好方法还是有更好的选择。
有任何想法吗?
解决方案
我将跟踪与手动更改检测结合使用(可能看起来很粗糙,但您helloComponents
在与从服务触发更新相同的事件循环滴答中手动更新数组),它似乎工作:
import { Component, ChangeDetectorRef } from '@angular/core';
import { StateService } from './state.service';
@Component({
selector: 'my-app',
template: `<hello *ngFor="let h of helloComponents, trackBy: trackById" [id]="h"></hello> <button (click)="action()">action</button>`
})
export class AppComponent {
name = 'Angular';
helloComponents = [1, 2, 3];
constructor(private stateService: StateService, private ref: ChangeDetectorRef) {}
action() {
this.helloComponents = [4, 5];
this.ref.detectChanges();
this.stateService.action();
}
trackById = id => id;
}
堆栈闪电战: https ://stackblitz.com/edit/angular-e9zfoq ?file=src/app/app.component.ts
推荐阅读
- php - Codeigniter 3.0.5 会话无法在线工作
- scala - 我如何减少卡夫卡消费者/生产者的滞后
- amazon-web-services - 如何调用 AWS SageMaker 终端节点来获取推理?
- date - DAX 中从星期一开始的会计年度周数
- python - 如何更改路径以使屏幕可以采用默认的python路径?
- ios - 选择该单元格时,如何将图像从照片库上传到特定的 collectionview 单元格?
- regex - 为什么在 React Component 中传递属性时不需要放置字符串转义字符
- python-3.x - 断言错误:
> 不是 - java - Android 中的离子条码扫描过程崩溃
- node.js - Webpack 已使用与 API 模式不匹配的配置对象进行初始化。通过“npm install webpack”安装 webpack