如何解决Backbone.js获取并设置嵌套对象属性
| 我对Backbone.js的get和set函数有一个简单的问题。 1)使用下面的代码,如何直接\'get \'或\'set \'obj1.myAttribute1? 另一个问题: 2)在模型中,除了默认对象之外,我还能/应该在何处声明模型的其他属性,以便可以通过Backbone的get和set方法对其进行访问?var MyModel = Backbone.Model.extend({
defaults: {
obj1 : {
\"myAttribute1\" : false,\"myAttribute2\" : true,}
}
})
var MyView = Backbone.View.extend({
myFunc: function(){
console.log(this.model.get(\"obj1\"));
//returns the obj1 object
//but how do I get obj1.myAttribute1 directly so that it returns false?
}
});
我知道我可以做:
this.model.get(\"obj1\").myAttribute1;
但这是好习惯吗?
解决方法
虽然
this.model.get(\"obj1\").myAttribute1
很好,但这还是有问题的,因为那样的话您可能会想为set做相同类型的事情,即
this.model.get(\"obj1\").myAttribute1 = true;
但是,如果这样做,您将无法获得myAttribute1
的Backbone模型的好处,例如更改事件或验证。
更好的解决方案是永远不要在模型中嵌套POJSO(“纯旧JavaScript对象”),而嵌套自定义模型类。所以看起来像这样:
var Obj = Backbone.Model.extend({
defaults: {
myAttribute1: false,myAttribute2: true
}
});
var MyModel = Backbone.Model.extend({
initialize: function () {
this.set(\"obj1\",new Obj());
}
});
然后访问代码将是
var x = this.model.get(\"obj1\").get(\"myAttribute1\");
但更重要的是,设置代码为
this.model.get(\"obj1\").set({ myAttribute1: true });
这将触发适当的更改事件等。此处的工作示例:http://jsfiddle.net/g3U7j/
, 我为此创建了骨架深层模型-只需扩展Backbone.DeepModel而不是Backbone.Model,然后即可使用路径获取/设置嵌套模型属性。它也维护变更事件。
model.bind(\'change:user.name.first\',function(){...});
model.set({\'user.name.first\': \'Eric\'});
model.get(\'user.name.first\'); //Eric
, Domenic的解决方案可以使用,但是每个新的MyModel都指向相同的Obj实例。
为了避免这种情况,MyModel应该如下所示:
var MyModel = Backbone.Model.extend({
initialize: function() {
myDefaults = {
obj1: new Obj()
}
this.set(myDefaults);
}
});
有关完整说明,请参见c3rin的答案@ https://stackoverflow.com/a/6364480/1072653。
, 我使用这种方法。
如果您有这样的骨干网模型:
var nestedAttrModel = new Backbone.Model({
a: {b: 1,c: 2}
});
您可以使用以下方法设置属性“ a.b”:
var _a = _.omit(nestedAttrModel.get(\'a\')); // from underscore.js
_a.b = 3;
nestedAttrModel.set(\'a\',_a);
现在,您的模型将具有以下属性:
{a: {b: 3,c: 2}}
触发了“更改”事件。
, 目前尚无人想到的一种解决方案可供使用。确实,您不能直接设置嵌套属性,除非您使用了可能不想要的第三方库。但是,您可以做的是克隆原始字典,在其中设置嵌套属性,然后设置整个字典。小菜一碟。
//How model.obj1 looks like
obj1: {
myAttribute1: false,myAttribute2: true,anotherNestedDict: {
myAttribute3: false
}
}
//Make a clone of it
var cloneOfObject1 = JSON.parse(JSON.stringify(this.model.get(\'obj1\')));
//Let\'s day we want to change myAttribute1 to false and myAttribute3 to true
cloneOfObject1.myAttribute2 = false;
cloneOfObject1.anotherNestedDict.myAttribute3 = true;
//And now we set the whole dictionary
this.model.set(\'obj1\',cloneOfObject1);
//Job done,happy birthday
, @Domenic \的解决方案对@pagewil和@Benno也有相同的问题。我的答案是改写一个简单的Backbone.Model子类来解决问题。
// Special model implementation that allows you to easily nest Backbone models as properties.
Backbone.NestedModel = Backbone.Model.extend({
// Define Backbone models that are present in properties
// Expected Format:
// [{key: \'courses\',model: Course}]
models: [],set: function(key,value,options) {
var attrs,attr,val;
if (_.isObject(key) || key == null) {
attrs = key;
options = value;
} else {
attrs = {};
attrs[key] = value;
}
_.each(this.models,function(item){
if (_.isObject(attrs[item.key])) {
attrs[item.key] = new item.model(attrs[item.key]);
}
},this);
return Backbone.Model.prototype.set.call(this,attrs,options);
}
});
var Obj = Backbone.Model.extend({
defaults: {
myAttribute1: false,myAttribute2: true
}
});
var MyModel = Backbone.NestedModel.extend({
defaults: {
obj1: new Obj()
},models: [{key: \'obj1\',model: Obj}]
});
NestedModel为您所做的就是允许这些工作(当通过JSON数据设置myModel时会发生这种情况):
var myModel = new MyModel();
myModel.set({ obj1: { myAttribute1: \'abc\',myAttribute2: \'xyz\' } });
myModel.set(\'obj1\',{ myAttribute1: 123,myAttribute2: 456 });
在初始化时自动生成模型列表会很容易,但是这个解决方案对我来说已经足够了。
, Domenic提出的解决方案有一些缺点。假设您想收听\'change \'事件。在这种情况下,不会启动\'initialize \'方法,并且您的属性自定义值将被服务器中的json对象替换。在我的项目中,我遇到了这个问题。我的解决方案来覆盖Model的'set \'方法:
set: function(key,val,options) {
if (typeof key === \'object\') {
var attrs = key;
attrs.content = new module.BaseItem(attrs.content || {});
attrs.children = new module.MenuItems(attrs.children || []);
}
return Backbone.Model.prototype.set.call(this,key,options);
},
, 尽管在某些情况下使用Backbone模型代替嵌套的Object属性是合理的,如Domenic所述,但在更简单的情况下,您可以在模型中创建setter函数:
var MyModel = Backbone.Model.extend({
defaults: {
obj1 : {
\"myAttribute1\" : false,\"myAttribute2\" : true,}
},setObj1Attribute: function(name,value) {
var obj1 = this.get(\'obj1\');
obj1[name] = value;
this.set(\'obj1\',obj1);
}
})
, 如果与后端交互,则需要具有嵌套结构的对象。
但是有了骨干,线性结构就更容易工作了。
bone.linear可以为您提供帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。