當我創建我的第一個有點複雜的Backbone應用程序時,我遇到了同樣的問題。伴隨着您對冗餘代碼的關注,我擔心綁定到導航欄的事件可能無法在導航欄更改時解除綁定。爲了解決這個問題,我創建了一個視圖層次結構,其中一個管理器視圖管理導航欄一個整體,併爲我想顯示的每種類型的導航菜單單獨視圖,這將被傳遞給管理器視圖來呈現到頁面。
下面是我的實施示例。
在我們開始之前,這裏是一個close
功能我加入到骨幹View
原型,解除綁定事件,並刪除了該視圖
Backbone.View.prototype.close = function() {
if(this.beforeClose) { this.beforeClose(); }
this.remove();
this.unbind();
}
首先,這裏是我的管理器視圖。其render
函數關閉當前顯示的任何菜單,並將其替換爲傳遞給它的那個爲view
。雖然略有冗餘,但我創建了一個明確的empty
函數,以使我的路由器代碼更易於理解。
var App.Views.SubNavBar = Backbone.View.extend({
currentView: null,
el: '#subnav-wrap',
render: function(view) {
if(this.currentView) { this.currentView.close(); }
this.currentView = view;
this.$el.html(view.el);
},
empty: function() {
if(this.currentView) { this.currentView.close(); }
this.currentView = null;
}
});
其次,這裏是一個基地認爲,所有的我的具體導航菜單視圖擴展。因爲它們都具有相同的tagName
,className
,id
,並initialize
和render
功能,這樣可保持的重複到最小
var App.Views.SubNavBase = Backbone.View.extend({
tagName: 'ul',
className: 'nav nav-pills',
id: 'subnav',
template: _.template($('#tmpl-subnav').html(),
initialize: function() {
if(this.setLinks) { this.setLinks(); }
this.render();
},
render: function() {
this.$el.html(this.template({links:this.links}));
return this;
}
});
這裏是用於特定導航菜單的圖的一個例子。您可以看到,我需要做的就是定義我想要在菜單中顯示的鏈接。當我實例化這個視圖時,SubNavBase
的功能將處理填充所需HTML的視圖。請注意,我也有一些事件附加到這個視圖。
var App.Views.Projects.DisplayNav = App.Views.SubNavBase.extend({
setLinks: function() {
this.links = {
'Edit Project': {
icon: 'edit',
class: 'menu-edit',
href: '#projects/'+this.model.get('id')+'/edit'
},
'Add Group': {
icon: 'plus',
class: 'menu-add-group',
href: '#projects/'+this.model.get('id')+'/groups/new'
},
'Delete Project': {
icon: 'trash',
class: 'menu-delete',
href: '#'
}
}
},
events: {
'click a.menu-delete' : 'delete'
},
delete: function(e) {
e.preventDefault();
// here goes my code to delete a project model
}
});
現在,這裏是underscore.js模板我用打開鏈接對象的上方爲<li>
元素的列表。請注意,我用<@
代替<%
我的模板,因爲這是一個Rails應用程序和Rails已經使用<%
<script type="text/template" id="tmpl-subnav">
<@ _.each(links,function(link, title) { @>
<li>
<a href="<@= link.href @>" class="<@= link.class @>">
<i class="icon-<@= link.icon @>"></i>
<@= link.title @>
</a>
</li>
<@ }); @>
</script>
最後,把它放在一起,這裏是創建和呈現導航菜單的例子Router
功能。是出現的步驟如下:
App.Views.Projects.DisplayNav
被傳遞模型,並填充其this.el
與相應的HTML,由underscore.js模板
App.SubNavBar
有其render
函數調用與新菜單視圖確定
App.SubNavBar
檢查導航欄中是否有其他菜單;如果是這樣,它調用視圖的close()
功能
App.SubNavBar
最後追加了通過視圖的HTML本身,保持與視圖的引用供以後使用
我只包括路由器代碼
的相關部分
var App.Routers.Projects = Backbone.Router.extend({
routes: {
'projects/:id' : 'display'
},
display: function(id) {
var p = projects.get(id);
var subnav = new App.Views.Projects.DisplayNav({model:p})
App.SubNavManager.render(subnav); // App.SubNavManager is an instance of App.Views.SubNavBar
}
});
的好處這一切的是,我現在可以將事件附加到我的菜單特定的觀點,如果用戶導航到不同的內容和菜單更改管理器視圖將採取取消綁定他們的照顧。
當然,還有許多其他模式可以用來處理導航菜單,但希望這可以幫助您走上正途。
哥們,真棒的答案。說實話,後來想到它,我意識到擁有視圖層次結構是最好的選擇。然後我看到了這一點,它非常詳細。再次感謝!!!! – 0xSina
@ 0xSina沒問題。我在經過一系列的嘗試之後,決定採用這種方法,這是我所喜歡的。我認爲,不如拯救別人的時間和麻煩。我還將「經理」方式擴展到我的應用的其他部分,並定期重新加載新內容。主要內容'div' – jackwanders