`DS.attr()`中的嵌套对象不受`DS.rollbackAttributes()的影响`

时间:2016-11-30 10:34:10

标签: ember.js ember-data

我有一个模型User如下:

import DS from 'ember-data';

const { attr, Model } = DS;

export default Model.extend({
  name: attr("string"),
  properties: attr(),
});

User.properties旨在保存JSON对象。

我正在通过表单(使用ember-one-way-controls)更新模型,如下所示:

{{one-way-textarea
  model.name
  update=(action (mut model.name))}}

{{one-way-textarea
  model.properties.description
  update=(action (mut model.properties.description))}}

我有一个按钮,允许用户通过调用discardChanges操作来放弃更改:

actions: {
  discardChanges(model) {
    model.rollbackAttributes();
  },
},

name属性更改已正确丢弃/重置,但properties属性未正确。

我该如何处理?

1 个答案:

答案 0 :(得分:2)

问题的根源

Ember Data并不知道这些变化,因为它使用===运算符将脏污属性与原始属性进行比较。如果发现了更改,Ember Data会将脏污的属性键存储在_attributes数组中。 We notice this here.然后,当您致电DS.rollbackAttributes()时,模型会查看_attributes以确认要恢复的属性。 Here it is.

但哈希是不一样的!

JS是关于通过引用传递的值的全部内容。以下是节点解释器的示例:

> var foo = { description: 'hello' }
undefined
> var bar = foo;
undefined
> bar.description = 'bonjour';
'bonjour'
> bar === foo
true

您正在修改原始对象。

<强>解决方案

一种可能的解决方案是深层复制properties对象,并在调用discardChanges时手动重置。

您可以将其实施为服务:

import Ember from 'ember';

const { copy, Service } = Ember;

export default Service.extend({
  savedProperties: null,

  finalize() {
    this.set('savedProperties', null);
  },

  start(model) {
    const properties = copy(model.get('properties'));
    this.set("savedProperties", properties);
  },

  undo(model) {
    const savedProperties = this.get('savedProperties');
    for (const property in savedProperties) {
      if (savedProperties.hasOwnProperty(property)) {
        const keyPath = `properties.${property}`;
        model.set(keyPath, savedProperties[property]);
      }
    }
    this.set('savedProperties', null);
  },
});
  • 当您进入编辑模式时,请致电start
  • 如果要放弃更改,请致电undo
  • 当您成功保存记录时,请致电finalize