Ember.js中嵌套数组内对象属性变化监听及计算属性实现方法
监听Ember.js中嵌套数组内对象的属性变化
这个问题在Ember开发里挺常见的——默认的计算属性不会自动深度追踪嵌套数组里对象的属性变化,得结合Ember的追踪机制来处理。下面分两种主流场景给你解决方案:
1. Ember Octane+(推荐,新版写法)
如果你的项目用的是Octane及以上版本,用@tracked属性是最简洁的方式。核心要点是:把嵌套数组里的对象改成带有@tracked属性的类实例,这样Ember能自动追踪属性变化。
代码示例
import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; // 定义可追踪的Item类,foo和bar都标记为@tracked class Item { @tracked foo; @tracked bar; constructor(foo, bar) { this.foo = foo; this.bar = bar; } } export default class MyComponent extends Component { // 外层数组也标记为@tracked,监听数组本身的增减/替换 @tracked nestedArray = [ [new Item("12", "34"), new Item("33", "55")], [new Item("45", "67")] ]; // 计算属性,自动追踪所有嵌套的foo/bar变化 get computedResult() { // 关键:遍历所有嵌套对象的属性,让Ember捕获到依赖关系 return this.nestedArray.flat().map(item => `foo: ${item.foo}, bar: ${item.bar}`).join(' | '); } }
为什么这样可行?
@tracked会自动追踪属性的读写,只要计算属性里访问了item.foo或item.bar,当这些值变化时,计算属性就会自动更新。- 外层数组标记
@tracked,能监听数组本身的增减、内层数组的替换等操作。
2. 旧版Ember(pre-Octane)
如果你的项目还在使用旧版Ember,需要手动指定计算属性的依赖键,同时确保内部对象是EmberObject实例(原生对象的属性变化Ember监听不到)。
代码示例
import Component from '@ember/component'; import { computed } from '@ember/object'; import EmberObject from '@ember/object'; // 用EmberObject定义Item,让属性可被监听 const Item = EmberObject.extend({ foo: null, bar: null }); export default Component.extend({ // 初始化嵌套数组,用Item.create创建实例 nestedArray: [ [Item.create({ foo: "12", bar: "34" }), Item.create({ foo: "33", bar: "55" })], [Item.create({ foo: "45", bar: "67" })] ], // 手动指定所有需要监听的依赖键 computedResult: computed( 'nestedArray.[]', // 监听外层数组的增减/替换 'nestedArray.@each.[]', // 监听每个内层数组的增减/替换 'nestedArray.@each.@each.foo', // 监听所有Item的foo变化 'nestedArray.@each.@each.bar', // 监听所有Item的bar变化 function() { return this.get('nestedArray').flat().map(item => `foo: ${item.get('foo')}, bar: ${item.get('bar')}`).join(' | '); } ) });
依赖键说明
nestedArray.[]:监听外层数组的结构变化(比如添加/移除内层数组)nestedArray.@each.[]:监听每个内层数组的结构变化(比如在内层数组里添加/移除Item)nestedArray.@each.@each.foo/bar:深度监听所有嵌套Item的属性变化
关键注意事项
- 必须用可追踪的对象:不管是Octane的
@tracked类还是旧版的EmberObject,原生JS对象的属性变化Ember是无法监听的,这是很多人踩坑的点。 - Octane写法里,计算属性需要实际访问到嵌套属性:如果只是返回数组本身,Ember不会追踪内部对象的变化,所以一定要遍历并读取
foo和bar。
内容的提问来源于stack exchange,提问作者Yelinz
相关产品推荐
相关产品推荐

