异步关联场景下,如何正确迁移@computed装饰器至@tracked结合getter的实现?
异步关联场景下,如何正确迁移@computed装饰器至@tracked结合getter的实现?
嗨,我明白你现在遇到的问题了——异步的hasMany关系确实给@computed转@tracked+getter带来了小麻烦,你之前的写法问题在于没有利用好Ember对异步关系的自动追踪机制,反而引入了额外的@tracked变量绕了弯路。
原来的@computed('comments.@each.authorName')会自动监听两个关键变化:一是异步comments加载完成的状态变化,二是每个comment的authorName属性更新。而你之前手动维护@tracked names的方式,并没有让getter真正依赖comments的状态,所以当comments从pending变为fulfilled时,getter不会自动重新计算,自然得不到正确的结果。
其实不需要额外的@tracked变量,直接在getter里处理异步状态就好,Ember的自动追踪会帮你搞定后续的更新:
@hasMany('comment', { async: true }) comments; get authorNames() { // 处理加载中的状态 if (this.comments.isPending) { return 'loading'; } // 可选:处理加载失败的情况 if (this.comments.isRejected) { return '加载评论失败'; } // 加载完成后,mapBy会自动追踪每个comment的authorName变化 return this.comments.mapBy('authorName').join(', '); }
这个写法能生效的原因是:
- 当异步comments处于pending状态时,getter返回"loading";一旦comments加载完成(
isPending变为false),Ember的追踪系统会检测到这个状态变化,自动重新运行getter,返回拼接好的作者名。 - 对于每个comment的
authorName变化,mapBy('authorName')会自动依赖每个comment的该属性,只要有任何一个comment的authorName更新,getter就会重新计算并返回最新的结果,和原来的@computed('comments.@each.authorName')效果完全一致。
如果需要更精细的控制(比如缓存计算结果),也可以结合@cached装饰器,但在这个场景下其实没必要,因为getter的依赖已经被Ember正确追踪了。
备注:内容来源于stack exchange,提问作者mate89
相关产品推荐
相关产品推荐

