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

how to check if nested attributes in backbone model have changed

本文关键字:属性 嵌套 是否 模型 何检查 检查      更新时间:2023-09-26

我的模型数据格式为 -

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

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

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

您只能将主干模型中的变更事件绑定到顶级属性。

这可以通过两种方式完成,要么通过将其作为可以完成的模型集合,要么通过使用深度模型插件(如 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

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

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

以下解决方案要求您像这样更新整个属性:

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

另请参阅对类似问题的良好回答。

当模型发生更改时,事件将获得三个条件:模型、更改的值和要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,这两种实现也将起作用。


旁注:由于您的问题要求对某些属性进行更改处理程序,因此我假设您正在侦听单个属性并单独更新视图的某些部分。考虑将模型拆分为仅具有enableddefault以及featurename属性的映射、列表或模型主干集合。然后,您的视图可以在"featureModelX"更改时进行渲染和更新。

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