如果在初始化时传递属性,则会忽略Backbone.js默认值

时间:2013-11-14 09:46:01

标签: javascript backbone.js

我遇到了非常不愉快的情况。

以下是模型初始化的代码:

var Model = Backbone.Model = function(attributes, options) {
    var attrs = attributes || {};
    options || (options = {});
    this.cid = _.uniqueId('c');
    this.attributes = {};
    if (options.collection) this.collection = options.collection;
    if (options.parse) attrs = this.parse(attrs, options) || {};
    attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
    this.set(attrs, options);
    this.changed = {};
    this.initialize.apply(this, arguments);
};

这里的问题是当模型在init上获取属性map时,如果属性已经存在则忽略默认值,并且在设置传递给构造函数的内容之前不会设置默认值。

逻辑上以为我会期望默认值始终在初始化时设置,然后在调用“set”方法时将替换值,这样我可以覆盖“set”方法来处理数组类型属性并将它们转换为像这样的集合:

set: function () {
    var firstArgument = arguments[0],
        attributesMap;
    if (_.isObject(firstArgument)) {
        //setting with attributes map
        attributesMap = firstArgument;
        _.each(attributesMap, function (value, attribute) {
            var modelAttribute = this.attributes[attribute];
            if (modelAttribute && modelAttribute instanceof Backbone.Collection) {
                modelAttribute.reset(value);
                delete attributesMap[attribute];
            }
        }, this);
    }

    return Backbone.Model.prototype.set.apply(this, arguments);
}

现在我正在做的是检查默认属性是否是Backbone.Collection的实例,如果是,我重置具有给定数组值的集合(保持相同的集合引用并允许视图或其他数据对象侦听该集合)并防止它被常规数组覆盖。

由于我之前在调用“set”方法时遇到的问题,它没有默认属性,我无法检查我想要操作的属性类型。

如何处理数组属性以及应该转换并作为Backbone.Collection处理的属性?

现在我只是改变了“默认”功能所做的事情而不是返回属性对象我这样做:

defaults: function () {
    this.attributes = {
        ...
    };
}

1 个答案:

答案 0 :(得分:0)

这取自Backbone来源

var Model = Backbone.Model = function(attributes, options) {
    var attrs = attributes || {};
    options || (options = {});
    this.cid = _.uniqueId('c');
    this.attributes = {};
    if (options.collection) this.collection = options.collection;
    if (options.parse) attrs = this.parse(attrs, options) || {};
    attrs = _.defaults({}, attrs, _.result(this, 'defaults'));    // (1)
    this.set(attrs, options);    
    this.changed = {};
    this.initialize.apply(this, arguments);
};

正如您在(1)中看到的,它使用下划线默认值,它只是在调用set之前合并对象覆盖。

我想你的问题的解决方案可能是两次调用set,如下所示:

    ...
    if (options.parse) attrs = this.parse(attrs, options) || {};

    this.set( _.result(this, 'defaults') , options);   // set the default attrs
    this.changed = {};
    this.set( _.defaults({}, attrs) , options);        // set the attrs as passed in arguments
    this.initialize.apply(this, arguments);
};

定义一个新模型并保持骨干源不受影响当然会更清晰。

虽然我可能猜到你想做什么,但我认为你应该考虑采用另一种方式。

我希望有所帮助!