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

如何在Ember中通过Model在页面间传递数据?现有方法数据丢失

在Ember中通过Model跨页面传递数据的正确实践

首先得先帮你排查下现有代码可能导致数据丢失的几个问题:

  1. 你的combineArray计算属性没有设置依赖项,它只会执行一次。如果model.ccList或者关联的cardtransactions是异步加载的,计算属性会在数据还没完全加载时就执行,自然会丢数据。
  2. 直接给Ember Data Model动态添加processedTrans属性是不规范的——ED的Model是基于预定义Schema的,未声明的属性不会被Ember的追踪系统监控,也可能在页面跳转时丢失。
  3. 用JSON.parse(JSON.stringify(transaction))这种粗暴的序列化方式,会丢失ED Model实例的追踪属性,甚至遗漏未加载的关联数据,这也是部分数据丢失的核心原因之一。

接下来给你一套正确的实现方案,完全符合你“通过更新Model传递数据”的需求:

1. 先在Model类中声明自定义属性

首先要在你的目标Model(比如对应的订单/账户Model)里,显式声明processedTrans属性,让Ember Data能正确追踪它:

// app/models/your-model.js
import Model, { attr, hasMany } from '@ember-data/model';

export default class YourModel extends Model {
  @hasMany('cc') ccList; // 假设这是你原有的关联属性
  @attr('array') processedTrans; // 声明数组类型的自定义属性
}

2. 修正计算属性的实现

调整计算逻辑,添加正确的依赖项,并用ED官方的方式处理Model数据:

combineArray: Ember.computed('model.ccList.@each.cardtransactions.[]', function() { 
  const trans = Ember.A(); 
  const that = this; 

  // 用forEach代替map(我们不需要返回新数组,只是遍历处理)
  this.get('model.ccList').forEach(card => { 
    const cardName = card.get('cardName'); 
    const cardNum = card.get('cardNum'); 

    card.get('cardtransactions').forEach(transaction => { 
      // 用ED的toJSON()方法序列化Model,避免丢失数据
      const transactionData = transaction.toJSON();
      
      const temp = {
        ...transactionData,
        cardName,
        cardNum,
        selected: false,
        handlingFee: that.setHandlingFee(transaction.get('localCurrencyAmount'))
      };

      // 直接创建Ember对象并加入数组
      trans.push(Ember.Object.create(temp));
    }); 
  }); 

  // 用set方法设置Model属性,确保Ember追踪变化
  this.set('model.processedTrans', trans); 
  console.log(this.get('model.processedTrans.firstObject')); 
  return this.get('model.processedTrans'); 
}),

这里的关键改进:

  • 依赖项model.ccList.@each.cardtransactions.[]确保当任何卡片的交易列表变化时,计算属性会重新执行
  • 用transaction.toJSON()代替粗暴的JSON序列化,完整保留Model的已加载数据
  • 用set方法更新Model属性,触发Ember的响应式更新

3. 确保异步数据预加载

如果cardtransactions是异步关联,一定要在路由的model钩子中预加载所有数据,避免计算属性执行时数据还没加载完成:

// app/routes/your-current-page.js
import Route from '@ember/routing/route';

export default class YourCurrentPageRoute extends Route {
  async model() {
    const model = await this.store.findRecord('your-model', 'target-id');
    
    // 预加载所有卡片的交易数据
    await Promise.all(
      model.get('ccList').map(card => card.get('cardtransactions'))
    );
    
    return model;
  }
}

4. 跨页面传递Model的正确方式

在跳转页面时,直接传递Model实例即可,Ember会自动维护实例的状态:

// 在控制器或组件中触发跳转
this.transitionTo('next-page', this.get('model'));

然后在目标路由中接收这个Model:

// app/routes/next-page.js
import Route from '@ember/routing/route';

export default class NextPageRoute extends Route {
  model(params, transition) {
    // 直接获取传递过来的Model实例
    return transition.to.model;
  }
}

这样目标页面的控制器和模板就能直接使用model.processedTrans,所有更新的属性都会完整保留。

内容的提问来源于stack exchange,提问作者3gwebtrain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:59:39