我的应用程序的逻辑非常简单。我有获取JSONP的模型(数据包含年,季度和季度包含不同的键:值)。获取数据后,View会侦听Model的“更改”事件,然后再渲染数据。到目前为止一切都很好。
但后来我需要听取“更改:年”/“更改:季度”并根据更改使用新网址获取数据。但当“改变:年”/“改变:季度”被解雇时,全球“变革”也被解雇了。
当然,如果我使用Collection而不是Model - 对我来说,theres是“重置”的。但在这种情况下,我不能轻易地听“变化:年” - 我必须创建更多的模型(年份,季度和季度中的每个键)。但我想保持应用程序简单。
还有其他方法吗?或者创造更多模型是不可避免的?
感谢。
UPD:仍然需要“更改”事件,因为模型必须在获取新数据后重新呈现。
解决方案:我创建了常用的控制器,它包含需要更改的属性。并在.url()方法中从Controller获取它们以修改url。我坚持使用Collection的fetch()/“reset”通知并在“更改”时使Controller成为监听器。因此,当我更改“年”/“季度”时,View会从Controller获取通知,并在相应的Collection抓取时 - 使用新URL获取。
答案 0 :(得分:1)
据我了解,如果仅change
或year
发生变更,您不希望收到全局模型quarter
事件,但您必须这样做。
因此,在接收全局更改事件时,您可以检查它是year
还是quarter
changed,并跳过正常的事件处理。像这样:
this.model.bind("change", this.render, this);
this.model.bind("change:year", this.fetchSomething, this);
this.model.bind("change:quarter", this.fetchSomething, this);
render : function(){
var attributesExceptYearAndQuarter = _.without(this.model.attributes, ['year', 'quarter'])
if(this.model.changedAttributes(attributesExceptYearAndQuarter).length > 0){
// do the rendering
}
}
答案 1 :(得分:1)
您可以在模型的更改侦听器中检查更改的属性。
var MyModel=Backbone.Model.extend({
initialize:function(){
this.bind("change",this.changeModel);
this.bind("change:year",this.changeYear);
},
changeModel:function(model,objs){
//Checking changed attributes
if (_.has(objs.changes,"year") || _.has(objs.changes,"quarter")) return this;
console.log("Processing",objs.changes);
return this;
},
changeYear:function(model,new_val){
console.log("year changed.",new_val);
return this;
}
});
var mymodel=new MyModel();
mymodel.set("year",2012);
mymodel.set("month",6);
如果您有关于侦听模型的更改事件的视图,则应该为模型添加不同的属性,并在此属性更改时侦听此属性的更改事件而不是模型的更改事件和渲染视图。如果您的“年”和“季度”属性没有更改属性,请在changeModel函数中更改此属性的值并触发侦听器。
//Edit changeModel as below
changeModel:function(model,objs){
//Checking changed attributes
if (_.has(objs.changes,"year") || _.has(objs.changes,"quarter")) return this;
this.set("rerender",!this.rerender); //Changing for triggering change event
return this;
},
//View's constructor function
initialize:function(){
this.model.bind("change:rerender",this.render);
}