如何检查骨干模型中的嵌套属性是否已更改

时间:2016-03-07 20:03:03

标签: javascript backbone.js

我的模型数据格式为 -

{
  feature1: {
    enabled: true,
    default: false
  },
  feature2: {
    enabled: true,
    default: false
  }
}

在我的代码中,我将其设置为this.model.get("feature1").enabled = false;

现在,当数据格式与上述类似时,如何检查模型是否更改了属性。

2 个答案:

答案 0 :(得分:1)

您只能将Backbone模型中的更改事件绑定到顶级属性。

这可以通过两种方式完成,或者通过将其作为可以完成的模型集合,或者使用深层模型插件(如https://github.com/kahwee/backbone-deep-model)。

所以它会变成:

var model = new Backbone.DeepModel({
   feature1: {
      enabled: true,
      default: false
   },
   feature2: {
      enabled: true,
      default: false
   }
});

model.on('change:feature1.* change:feature2.*', function(model, val) {
    console.log(val);
});

model.set({
  'feature1.enabled': false
});

jsbin示例 - https://jsbin.com/gatuyadoji/edit?js,console,output

答案 1 :(得分:0)

在显示可能的解决方案之前,让我告诉您考虑是否真的需要单独的嵌套属性更改。在功能更改时更新视图可能不会花费那么多时间,因为您需要担心。

如果只有一个视图需要检测嵌套模型属性中的属性更改,那么听取更改事件就足够了,因为您可以在更改事件时检测到各个属性的更改。

以下解决方案要求您更新整个属性,如下所示:

model.set("feature1", _.extend({ }, model.get("feature1"), { enabled: false }));

还请refer to this good answer to a similar question

当模型发生变化时,事件会得到三个标记:模型,更改的值和set()的选项以及模型存储以前的值 - 在您的情况下是对象的对象 - 在_previousAttributes

model.on("change:feature1", function(model, value) {
    var prev = model._previousAttributes;

    if (model.get("feature1").enabled !== prev.feature1.enabled) {
        // update upon change of "enabled"
    }

    if (model.get("feature1").default !== prev.feature1.default) {
        // update upon change of "default"
    }
});

由于此代码对于每个"功能而言都有点笨重。你可以写一个单独的帮手:

// returns an object which maps a key difference to true to easily check
// using "key" in obj
function objDiff(a, b) {
    var keys = _.union(_.keys(a), _.keys(b)), isDef = {};
    _.each(keys, function(key) {
        if (a[key] !== b[key]) {
            isDef[key] = true;
        }
    });
    return isDef;
}

以这种方式检查属性更改:

model.on("change:feature1", function(model, value) {
    var changed = objDiff(model.get("feature1"), model._previousAttributes.feature1);

    if ("enabled" in changed) {
        // update upon change of "enabled"
    }

    if ("default" in changed) {
        // update upon change of "default"
    }
});

如果您只是在监听change,这两种实现方式也会有效。

旁注:由于您的问题要求对某些属性进行更改处理程序,因此我假设您正在侦听各个属性并单独更新视图的某些部分。考虑将模型拆分为仅具有enableddefaultfeaturename属性的地图,列表或Backbone模型集合。然后,您的视图可以在" featureModelX"上呈现和更新。变化。

var FeatureModel = Backbone.Model({
    defaults: {
        enabled: false,
        default: false
    }
});

new FeatureModel({feature: "feature1"});