我正在开发我的第一个RequireJS / Backbone应用程序而且我已经碰壁了。这里有很多代码味道,我知道我只是缺少模式。
我有一条路线显示所有促销活动,另一条显示特定促销活动(按ID):
showPromotions: function () {
var promotionsView = new PromotionsView();
},
editPromotion: function (promotionId) {
vent.trigger('promotion:show', promotionId);
}
在我的促销视图初始化程序中,我新推出了我的PromotionsCollection&取。我还订阅了集合上的重置事件。这称为addAll,最终构建了所有Promotions& amp;将它附加到DOM中的容器div。
define([
'jquery',
'underscore',
'backbone',
'app/vent',
'models/promotion/PromotionModel',
'views/promotions/Promotion',
'collections/promotions/PromotionsCollection',
'text!templates/promotions/promotionsListTemplate.html',
'views/promotions/Edit'
], function ($, _, Backbone, vent, PromotionModel, PromotionView, PromotionsCollection, promotionsListTemplate, PromotionEditView) {
var Promotions = Backbone.View.extend({
//el: ".main",
tagName: 'ul',
initialize: function () {
this.collection = new PromotionsCollection();
this.collection.on('reset', this.addAll, this);
this.collection.fetch();
},
render: function () {
$("#page").html(promotionsListTemplate);
return this;
},
addAll: function () {
//$("#page").html(promotionsListTemplate);
this.$el.empty().append('<li class="hide hero-unit NoCampaignsFound"><p>No campaigns found</p></li>');
this.collection.each(this.addOne, this);
this.render();
$("div.promotionsList").append(this.$el);
},
addOne: function (promotion) {
var promotionView = new PromotionView({ model: promotion });
this.$el.append(promotionView.render().el);
}
});
return Promotions;
});
列表中的每个促销都有一个href为#promotion/edit/{id}
的编辑按钮。如果我先导航到列表页面,然后单击编辑,它就可以正常工作。但是,我无法直接导航到编辑页面。我理解这是因为我在我的View上的initialize方法中填充了我的集合。我可以使用“if collection.length == 0,fetch”类型的调用,但我更喜欢不需要执行此类检查的设计。我的问题:
addAll
方法中调用渲染来拉入我的模板。我当然可以将代码移到addAll
,但总的来说这段代码也很有气味。我应该有一个负责呈现模板本身的“父视图”,并根据需要实例化我的列表/编辑视图吗? 谢谢!
答案 0 :(得分:2)
这是一次拍摄。请记住,有多种方法可以做到这一点。事实上,这可能不是最好的,但我自己这样做,所以也许其他人可以帮助我们两个!
首先,你在这个js文件中有很多导入。如果您按照以下方式添加/删除内容,则随着时间的推移,管理起来要容易得多:
define(function( require ){
// requirejs - too many includes to pass in the array
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone'),
Ns = require('namespace'),
Auth = require('views/auth/Auth'),
SideNav = require('views/sidenav/SideNav'),
CustomerModel = require('models/customer/customer');
// blah blah blah...});
这只是一种风格建议,但是你的电话。至于收集业务,这样的事情:
Forms.CustomerEdit = Backbone.View.extend({
template: _.template( CustomerEditTemplate ),
initialize: function( config ){
var view = this;
view.model.on('change',view.render,view);
},
deferredRender: function ( ) {
var view = this;
// needsRefresh decides if this model needs to be fetched.
// implement on the model itself when you extend from the backbone
// base model.
if ( view.model.needsRefresh() ) {
view.model.fetch();
} else {
view.render();
}
},
render:function () {
var view = this;
view.$el.html( view.template({rows:view.model.toJSON()}) );
return this;
}
});
CustomerEdit = Backbone.View.extend({
tagName: "div",
attributes: {"id":"customerEdit",
"data-role":"page"},
template: _.template( CustomerEditTemplate, {} ),
initialize: function( config ){
var view = this;
// config._id is passed in from the router, as you have done, aka promotionId
view._id = config._id;
// build basic dom structure
view.$el.append( view.template );
view._id = config._id;
// Customer.Foo.Bar would be an initialized collection that this view has
// access to. In this case, it might be a global or even a "private"
// object that is available in a closure
view.model = ( Customer.Foo.Bar ) ? Customer.Foo.Bar.get(view._id) : new CustomerModel({_id:view._id});
view.subViews = {sidenav:new Views.SideNav({parent:view}),
auth:new Views.Auth(),
editCustomer: new Forms.CustomerEdit({parent:view,
el:view.$('#editCustomer'),
model:view.model})
};
},
render:function () {
var view = this;
// render stuff as usual
view.$('div[data-role="sidetray"]').html( view.subViews.sidenav.render().el );
view.$('#security').html( view.subViews.auth.render().el );
// magic here. this subview will return quickly or fetch and return later
// either way, since you passed it an 'el' during init, it will update the dom
// independent of this (parent) view render call.
view.subViews.editCustomer.deferredRender();
return this;
}
同样,这只是一种方式而且可能是非常错误的,但它是我如何做到的,它似乎工作得很好。我经常把'#34; loading&#34;子视图最终用替换html呈现的dom中的消息。