Ember.js:不使用@computed如何在另一个getter中追踪getter变化
不使用@computed追踪getter的加载状态
问题背景
需要在不使用@computed('currentApplications.isFulfilled')装饰器的前提下,让applicationsLoaded getter能追踪currentApplications.isFulfilled的状态变化。现有代码如下:
@computed('current.locationId') get currentApplications() { const query = { locationID: get(this, 'current.locationId') }; return this.store.pagedArray(this.store.query('shift-application', query)); } get applicationsLoaded() { return this.currentApplications.isFulfilled }
解决方案
方法1:利用Ember自动依赖追踪(适用于模板或响应式上下文场景)
在Ember 3.13及以上版本中,普通getter会自动追踪内部访问的响应式属性(包括computed属性和@tracked属性)。只要applicationsLoaded是在模板中使用,或是被其他响应式上下文(比如另一个computed属性)引用,Ember会自动监听currentApplications.isFulfilled的变化并更新applicationsLoaded的值,原代码无需修改即可正常工作。
方法2:手动监听属性变化(适用于类内部非响应式场景)
如果需要在类内部非响应式逻辑中也能获取最新状态,可以通过添加观察者手动同步状态:
import { tracked } from '@glimmer/tracking'; import { computed, get } from '@ember/object'; import { addObserver, removeObserver } from '@ember/object/observers'; // ... @tracked _applicationsLoaded = false; _previousPagedArray = null; @computed('current.locationId') get currentApplications() { const query = { locationID: get(this, 'current.locationId') }; const pagedArray = this.store.pagedArray(this.store.query('shift-application', query)); // 清理旧的观察者,避免重复监听 if (this._previousPagedArray) { removeObserver(this._previousPagedArray, 'isFulfilled', this, '_updateLoadedState'); } // 监听新实例的isFulfilled变化 addObserver(pagedArray, 'isFulfilled', this, '_updateLoadedState'); // 初始化当前状态 this._updateLoadedState(pagedArray); // 保存实例用于后续清理 this._previousPagedArray = pagedArray; return pagedArray; } get applicationsLoaded() { return this._applicationsLoaded; } _updateLoadedState(pagedArray) { this._applicationsLoaded = pagedArray?.isFulfilled || false; } // 组件销毁时清理观察者,避免内存泄漏 willDestroy() { super.willDestroy(...arguments); if (this._previousPagedArray) { removeObserver(this._previousPagedArray, 'isFulfilled', this, '_updateLoadedState'); } }
方法3:通过Promise回调更新状态(仅适用于单次加载场景)
因为store.query返回Promise,可直接通过回调更新加载状态,但这种方式仅能捕获初始加载的完成/失败,无法追踪分页等后续状态变化:
import { tracked } from '@glimmer/tracking'; import { computed, get } from '@ember/object'; // ... @tracked _applicationsLoaded = false; @computed('current.locationId') get currentApplications() { const query = { locationID: get(this, 'current.locationId') }; const promise = this.store.query('shift-application', query); const pagedArray = this.store.pagedArray(promise); // 初始化状态为未加载 this._applicationsLoaded = false; // 加载完成/失败后更新状态 promise .then(() => { this._applicationsLoaded = true; }) .catch(() => { // 可按需处理失败场景,比如标记加载失败 this._applicationsLoaded = true; }); return pagedArray; } get applicationsLoaded() { return this._applicationsLoaded; }
内容的提问来源于stack exchange,提问作者KingStar1001
相关产品推荐
相关产品推荐

