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

Ember Octane中Tracked属性变更时get函数未重新计算问题

问题原因分析
  • 核心问题:@tracked对Ember可变数组的内部变更不敏感。@tracked追踪的是属性的引用变化,你用A([])创建的Ember数组是可变对象,调用pushObject/removeObject只会修改数组内部内容,不会改变数组本身的引用,因此tracked无法感知到变化,导致availableAppDefinitions的getter不会重新计算。
  • 尝试@computed时无效,是因为依赖键写法错误:只写selectedAppCategories只会追踪数组引用的变化,要追踪数组内容的变更,必须加上.[]后缀,即'selectedAppCategories.[]'。
解决方案

两种推荐方案二选一即可:

方案一:原生JavaScript数组 + @tracked

将Ember数组替换为原生数组,通过替换整个数组的方式修改内容,让@tracked捕获到引用变化:

import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import Controller from '@ember/controller';

export default class IntegrationActivationIndexController extends Controller {
  @service session;
  @service router;

  @tracked selectedAppCategories = []; // 使用原生数组

  get availableAppDefinitions() {
    let filteredAppCategories = this.selectedAppCategories;
    return this.model.app.filter(app => 
      app.categories.some(appCategory => filteredAppCategories.includes(appCategory.name))
    );
  }

  @action
  onChangeCategory(category) {
    if (this.selectedAppCategories.includes(category)) {
      // 过滤得到新数组
      this.selectedAppCategories = this.selectedAppCategories.filter(item => item !== category);
    } else {
      // 拼接得到新数组
      this.selectedAppCategories = [...this.selectedAppCategories, category];
    }
  }
}

说明:原生数组的替换操作会改变selectedAppCategories的引用,@tracked能捕获到这个变化,从而触发getter重新计算。另外将原代码中filter+length的判断改为some,更高效(找到第一个匹配项就停止遍历)。

方案二:Ember数组 + @computed(修正依赖键)

如果坚持使用Ember数组,需要修正@computed的依赖键,确保追踪数组内容的变更:

import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { computed } from '@ember/object';
import Controller from '@ember/controller';
import { A } from '@ember/array';

export default class IntegrationActivationIndexController extends Controller {
  @service session;
  @service router;

  selectedAppCategories = A([]); // 无需@tracked,由computed追踪

  @computed('selectedAppCategories.[]', 'model.app.[]') // 加.[]追踪内容变更
  get availableAppDefinitions() {
    let filteredAppCategories = this.selectedAppCategories;
    return this.model.app.filter(app => 
      app.categories.some(appCategory => filteredAppCategories.includes(appCategory.name))
    );
  }

  @action
  onChangeCategory(category) {
    if (this.selectedAppCategories.includes(category)) {
      this.selectedAppCategories.removeObject(category);
    } else {
      this.selectedAppCategories.pushObject(category);
    }
  }
}

说明:selectedAppCategories.[]表示追踪数组的内容变更(新增、删除元素),model.app.[]确保当model中的app数组变化时也会重新计算,这样computed就能正确响应数组内部的修改。

额外模板修正

模板中input的value绑定有误,循环变量是appCategory,不是this.model.appCategory,同时建议给id加唯一后缀避免重复:

{{#each this.model.appCategories as |appCategory|}}
    <input id="checkbox_id_{{appCategory.name}}" value="{{appCategory.name}}" type="checkbox" onchange={{action (fn this.onChangeCategory) appCategory.name}}>
{{/each}}

<div>
  {{my-component value=availableAppDefinitions}}
</div>

内容的提问来源于stack exchange,提问作者Pierre Girardeau

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 13:43:20