angular - 使用 Observables 组合视图模型
问题描述
下面的代码简单地说明了我试图用 2 个模型做什么。假设我们有一个Book
模型和一个Author
模型。首先,我们获取Books
使用返回类型的服务的列表Observable<Book>
。然后我们使用*ngFor
遍历每一个,但我们还想Author
在书的旁边显示,所以在我们的迭代中,我们有一些像这样的 HTML:
<span>{{ getAuthorName(book) | async }}</span>
getAuthorName
有自己的请求AuthorService
就去取作者ID
。问题是,当我们在Observable<string>
这里返回时,浏览器完全崩溃,因为更改检测运行异常,因为每个摘要周期都返回一个“新”可观察对象,这导致更改检测再次无休止地运行,对吗?
下面的代码可以很容易地放入 StackBlitz 并复制(我没有链接到它,因为它会炸毁你的浏览器 CPU)
<ul>
<li *ngFor="let item of getData() | async">
{{ getOtherData(item.id) | async }}
</li>
</ul>
import { Component } from '@angular/core';
import { of } from 'rxjs';
import { filter, map } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
getData() {
return of([{
id: 1
},{
id: 2
},{
id: 3
}]);
}
getOtherData(id: number) {
const data = of([{
id: 1,
name: 'Matt'
},{
id: 2,
name: 'Steve'
},{
id: 3,
name: 'Alice'
}]);
return data.pipe(
map(x => x.find(d => d.id == id))
)
}
}
显然有一些优化,比如缓存作者等,可以在这里完成,但总的来说,在 RXJS 的世界中应该如何处理这种情况?我知道有完整的框架来处理像 Akita 和 ngrx 这样的状态,但是如果我不想处理所有这些并且只想用 raw 构建我的应用程序rxjs
怎么办?这个问题的预期解决方案是什么?您是否使用其他一些 rxjs 运算符来阻止这种情况发生?(我找不到任何对此有帮助的东西,因为它Obserable
每次都返回一个新的)你必须只使用视图模型而不是方法吗?这样,ei 总是只是对 observable 的一个引用?(例如,在我们将视图迭代到单个可观察对象之前,BookAuthorViewModel
哪个属性会被设置?$author
我还没有找到一个“感觉正确”的解决方案,我觉得我被迫使用这些状态管理框架只是为了做这样的简单事情。
解决方案
你不应该在你的视图中调用方法。如果您有一个返回 observable 的方法,那么每次更改保留检查值时都会创建一个新的 observable。
data$ = of([{
id: 1
},{
id: 2
},{
id: 3
}]);
otherData$ = of([{
id: 1,
name: 'Matt'
},{
id: 2,
name: 'Steve'
},{
id: 3,
name: 'Alice'
}]);
然后绑定到 observable
<li *ngFor="let item of data$ | async">
{{ otherData$ | async | find: item.id }}
</li>
并制作查找管道
@Pipe({
name: 'find'
})
export class FindPipe implements PipeTransform {
transform(options, id): string {
return options.find(option => option.id === id);
}
}
StackBlitz https://stackblitz.com/edit/angular-6vgosc
推荐阅读
- python - 如何通过 Python 从 MP3 文件中访问/修改 [评论、组描述、心情] 属性
- command-prompt - 尝试执行机器代码时出错
- amazon-s3 - 我的反应应用程序中的自定义 s3 图像路径名
- python - 在python的同一目录中合并数据框中的多个json文件
- c# - 如何在 C# 中将数字列表一分为二?
- javascript - 类型 [] 打字稿上不存在属性
- django-serializer - Django Serializer 的问题涉及带有 null 和布尔值 true 或 false 的嵌套 JSON
- amazon-web-services - 发布到 SNS 主题的消息在没有订阅时可访问的任何详细信息?
- jq - 试图从 JQ 获得正确的输出
- c++ - 如何使数组的元素为空?