2012-07-03 74 views
1

我正在編寫我的第一個Backbone.js應用程序,我在編寫出編程它的最佳方法時遇到了一些麻煩。我有2個主要意見:Backbone.js路由器/視圖邏輯

  1. 顯示我所有模型的索引。
  2. 顯示編輯的特定模型。

但是#2有許多不同的「模塊」像我可以編輯「新聞」一節,或「關於」一節等等 所有這些模塊都在一個導航欄。

當我顯示視圖#1(所有模型的索引)時,隱藏導航欄。它在視圖#2(特定模型)中可見,以便在不同模塊之間導航。

我有路線的設置是這樣的:

routes: { 
    '', 'index', 
    'communities': 'index', 
    'communities/:id': 'main', 
    'communities/:id/news', 'news', 
    'communities/:id/about', 'about' 
}, 

所以我的問題是,當「新聞」或「關於」動作被調用,我在每個方法中添加一個導航欄?這不是多餘的嗎?我將擁有8-10個不同的模塊,每次添加導航欄似乎都非常重複。有沒有更好的辦法? 我想讓導航欄隱藏的唯一時間是顯示索引時。

回答

6

當我創建我的第一個有點複雜的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; 
    } 

}); 

其次,這裏是一個基地認爲,所有的我的具體導航菜單視圖擴展。因爲它們都具有相同的tagNameclassNameid,並initializerender功能,這樣可保持的重複到最小

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 
    } 
}); 

的好處這一切的是,我現在可以將事件附加到我的菜單特定的觀點,如果用戶導航到不同的內容和菜單更改管理器視圖將採取取消綁定他們的照顧。

當然,還有許多其他模式可以用來處理導航菜單,但希望這可以幫助您走上正途。

+0

哥們,真棒的答案。說實話,後來想到它,我意識到擁有視圖層次結構是最好的選擇。然後我看到了這一點,它非常詳細。再次感謝!!!! – 0xSina

+0

@ 0xSina沒問題。我在經過一系列的嘗試之後,決定採用這種方法,這是我所喜歡的。我認爲,不如拯救別人的時間和麻煩。我還將「經理」方式擴展到我的應用的其他部分,並定期重新加載新內容。主要內容'div' – jackwanders

1

試試這個:

routes: { 
    '', 'index', 
    'communities': 'index', 
    'communities/:id': 'main', 
    'communities/:id/:section': 'openSection' 
}, 
openSection : function(id, section){ 
    if(section){ 
     this.addNavigationBar(); 
    } 
    switch(section){ 
     case 'news' : 
      this.news(); 
      break; 
     case 'about' : 
      this.about(); 
      break; 
     default: 
      this.main(); 
    } 
} 

如果您的網址內容的部分,您將添加導航欄,然後打電話給你正常的方法,你有。