You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 05:35:29