初めてやや複雑な Backbone アプリを作成したときに、これと同じ問題に遭遇しました。冗長なコードに関するあなたの懸念に加えて、ナビゲーション バーが変更されたときにバインドが解除されない可能性がある、ナビゲーション バーにバインドされたイベントについて懸念していました。この問題を解決するために、ビュー階層を作成し、1 つのマネージャービューでナビゲーション バー全体を管理し、表示したいナビゲーション メニューの種類ごとに個別のビューを作成しました。ページ。
これが私の実装例です。
始める前に、close
Backbone のView
プロトタイプに追加した、イベントのバインドを解除してビューを削除する関数を次に示します。
Backbone.View.prototype.close = function() {
if(this.beforeClose) { this.beforeClose(); }
this.remove();
this.unbind();
}
まず、これが私のManager Viewです。その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
}
});
<li>
次に、上記のリンク オブジェクトを要素のリストに変換するために使用する underscore.js テンプレートを示します。これはレールアプリであり、レールはすでに使用しているため、テンプレート<@
の代わりに使用することに注意してください<%
<%
<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
れ、underscore.js テンプレートで決定された対応する HTMLが入力されます
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
}
});
これらすべての利点は、メニュー固有のビューにイベントをアタッチできるようになったことです。ユーザーが別のコンテンツに移動してメニューが変更された場合、マネージャー ビューがそれらのバインドを解除します。
もちろん、ナビゲーション メニューを処理するために使用できるパターンは他にもたくさんありますが、うまくいけば、これがその道のりで役立つことを願っています。