Backbone.js 将模型添加到集合问题
Posted
技术标签:
【中文标题】Backbone.js 将模型添加到集合问题【英文标题】:Backbone.js Adding Model to Collection Issue 【发布时间】:2012-01-19 20:01:09 【问题描述】:我正在 Backbone.js 中构建一个测试应用程序(我的第一个使用 Backbone 的应用程序)。该应用程序是这样的:
-
从服务器“计划”加载数据
建立计划列表并显示在屏幕上
有一个添加新计划的按钮
添加新计划后,添加到集合中(暂时不要保存到服务器)
重定向到索引页面并显示新集合(包括您刚刚添加的计划)
我的问题是第 5 项。当我保存计划时,我将模型添加到集合中,然后重定向到初始视图。此时,我从服务器获取数据。当我从服务器获取数据时,这会覆盖我的集合并且我添加的模型消失了。
如何防止这种情况发生?我找到了一种方法来做到这一点,但这绝对不是正确的方法。您将在下面找到我的代码示例。谢谢您的帮助。
PlansListView 视图:
var PlansListView = Backbone.View.extend(
tagName : 'ul',
initialize : function()
_.bindAll( this, 'render', 'close' );
//reset the view if the collection is reset
this.collection.bind( 'reset', this.render , this );
,
render : function()
_.each( this.collection.models, function( plan )
$( this.el ).append( new PlansListItemView( model: plan ).render().el );
, this );
return this;
,
close : function()
$( this.el ).unbind();
$( this.el ).remove();
);//end
NewPlanView保存方法
var NewPlanView = Backbone.View.extend(
tagName : 'section',
template : _.template( $( '#plan-form-template' ).html() ),
events :
'click button.save' : 'savePlan',
'click button.cancel' : 'cancel'
,
intialize: function()
_.bindAll( this, 'render', 'save', 'cancel' );
,
render : function()
$( '#container' ).append( $( this.el ).html(this.template( this.model.toJSON() )) );
return this;
,
savePlan : function( event )
this.model.set(
name : 'bad plan',
date : 'friday',
desc : 'blah',
id : Math.floor(Math.random()*11),
total_stops : '2'
);
this.collection.add( this.model );
app.navigate('', true );
event.preventDefault();
,
cancel : function()
);
路由器(默认方式):
index : function()
this.container.empty();
var self = this;
//This is a hack to get this to work
//on default page load fetch all plans from the server
//if the page has loaded ( this.plans is defined) set the updated plans collection to the view
//There has to be a better way!!
if( ! this.plans )
this.plans = new Plans();
this.plans.fetch(
success: function()
self.plansListView = new PlansListView( collection : self.plans );
$( '#container' ).append( self.plansListView.render().el );
if( self.requestedID ) self.planDetails( self.requestedID );
);
else
this.plansListView = new PlansListView( collection : this.plans );
$( '#container' ).append( self.plansListView.render().el );
if( this.requestedID ) self.planDetails( this.requestedID );
,
新计划路线:
newPlan : function()
var plan = new Plan(name: 'Cool Plan', date: 'Monday', desc: 'This is a great app');
this.newPlan = new NewPlanView( model : plan, collection: this.plans );
this.newPlan.render();
完整代码 (函数($)
var Plan = Backbone.Model.extend(
defaults:
name : '',
date : '',
desc : ''
);
var Plans = Backbone.Collection.extend(
model : Plan,
url : '/data/'
);
$( document ).ready(function( e )
var PlansListView = Backbone.View.extend(
tagName : 'ul',
initialize : function()
_.bindAll( this, 'render', 'close' );
//reset the view if the collection is reset
this.collection.bind( 'reset', this.render , this );
,
render : function()
_.each( this.collection.models, function( plan )
$( this.el ).append( new PlansListItemView( model: plan ).render().el );
, this );
return this;
,
close : function()
$( this.el ).unbind();
$( this.el ).remove();
);//end
var PlansListItemView = Backbone.View.extend(
tagName : 'li',
template : _.template( $( '#list-item-template' ).html() ),
events :
'click a' : 'listInfo'
,
render : function()
$( this.el ).html( this.template( this.model.toJSON() ) );
return this;
,
listInfo : function( event )
);//end
var PlanView = Backbone.View.extend(
tagName : 'section',
events :
'click button.add-plan' : 'newPlan'
,
template: _.template( $( '#plan-template' ).html() ),
initialize: function()
_.bindAll( this, 'render', 'close', 'newPlan' );
,
render : function()
$( '#container' ).append( $( this.el ).html( this.template( this.model.toJSON() ) ) );
return this;
,
newPlan : function( event )
app.navigate( 'newplan', true );
,
close : function()
$( this.el ).unbind();
$( this.el ).remove();
);//end
var NewPlanView = Backbone.View.extend(
tagName : 'section',
template : _.template( $( '#plan-form-template' ).html() ),
events :
'click button.save' : 'savePlan',
'click button.cancel' : 'cancel'
,
intialize: function()
_.bindAll( this, 'render', 'save', 'cancel' );
,
render : function()
$( '#container' ).append( $( this.el ).html(this.template( this.model.toJSON() )) );
return this;
,
savePlan : function( event )
this.model.set(
name : 'bad plan',
date : 'friday',
desc : 'blah',
id : Math.floor(Math.random()*11),
total_stops : '2'
);
this.collection.add( this.model );
app.navigate('', true );
event.preventDefault();
,
cancel : function()
);
var AppRouter = Backbone.Router.extend(
container : $( '#container' ),
routes :
'' : 'index',
'viewplan/:id' : 'planDetails',
'newplan' : 'newPlan'
,
initialize: function()
,
index : function()
this.container.empty();
var self = this;
//This is a hack to get this to work
//on default page load fetch all plans from the server
//if the page has loaded ( this.plans is defined) set the updated plans collection to the view
//There has to be a better way!!
if( ! this.plans )
this.plans = new Plans();
this.plans.fetch(
success: function()
self.plansListView = new PlansListView( collection : self.plans );
$( '#container' ).append( self.plansListView.render().el );
if( self.requestedID ) self.planDetails( self.requestedID );
);
else
this.plansListView = new PlansListView( collection : this.plans );
$( '#container' ).append( self.plansListView.render().el );
if( this.requestedID ) self.planDetails( this.requestedID );
,
planDetails : function( id )
if( this.plans )
this.plansListView.close();
this.plan = this.plans.get( id );
if( this.planView ) this.planView.close();
this.planView = new PlanView( model : this.plan );
this.planView.render();
else
this.requestedID = id;
this.index();
if( ! this.plans ) this.index();
,
newPlan : function()
var plan = new Plan(name: 'Cool Plan', date: 'Monday', desc: 'This is a great app');
this.newPlan = new NewPlanView( model : plan, collection: this.plans );
this.newPlan.render();
);
var app = new AppRouter();
Backbone.history.start();
);
)( jQuery );
【问题讨论】:
【参考方案1】:我认为您正在寻找“remove”参数,它将防止模型在提取期间从集合中删除。
this.plans.fetch(remove: false)
有关 fetch 方法的更多详细信息,请参阅backbone documentation。
【讨论】:
【参考方案2】:您是否每次点击索引页面时都获取数据,因为您希望列表与数据库同步(即其他人添加了一个项目并且您希望它反映)?
如果不是不是,我觉得你正在做的事情很好;仅当数据不存在时才获取。
但是,如果您确实希望列表保持同步;但是您仍然希望在其中呈现新添加的项目;您可以从获取的列表中合并或使用另一个列表来保存新添加的数据。
如果你使用另一个列表,你只需要渲染两个列表;未保存的列表可能应该存在于持久列表的顶部或底部,并组合在一起。
【讨论】:
不,我不需要列表与每个索引视图上的服务器同步。但是,您建议如何进行您所说的合并? 您可以通过模型的 id .get(id) 获取模型,并使用新获取的列表对其进行更新;或者使用集合的 .parse() 方法将所有未保存的模型添加到新列表中。 也许这可能会有所帮助:(来自 Collection 的 fetch 方法的主干文档)“如果您想将传入的模型添加到当前集合中,而不是替换集合的内容,请通过 add : true 作为获取的选项。”以上是关于Backbone.js 将模型添加到集合问题的主要内容,如果未能解决你的问题,请参考以下文章