1

私は最初のBackbone.jsアプリケーションを書いていますが、それをプログラムするための最良の方法を見つけるのに苦労しています。私は2つの主な見解を持っています:

  1. すべてのモデルのインデックスを表示します。
  2. 編集用の特定のモデルを表示します。

しかし、#2には、「ニュース」セクションや「アバウト」セクションなどを編集できるように、さまざまな「モジュール」があります。これらのモジュールはすべてナビゲーションバーにあります。

ビュー#1(すべてのモデルのインデックス)を表示しているとき、そのナビゲーションバーは非表示になっています。異なるモジュール間を移動するために、ビュー#2(特定のモデル)に表示されます。

私はこのようにルートを設定しています:

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

だから私の質問は、「ニュース」または「アバウト」アクションが呼び出されたときに、各メソッドにナビゲーションバーを追加するのですか?それは冗長ではありませんか?私は8-10の異なるモジュールを持っているつもりです、毎回ナビゲーションバーを追加することは非常に繰り返しのようです。もっと良い方法はありますか?ナビゲーションバーを非表示にしたいのは、インデックスを表示するときだけです。

4

2 に答える 2

6

初めてやや複雑な Backbone アプリを作成したときに、これと同じ問題に遭遇しました。冗長なコードに関するあなたの懸念に加えて、ナビゲーション バーが変更されたときにバインドが解除されない可能性がある、ナビゲーション バーにバインドされたイベントについて懸念していました。この問題を解決するために、ビュー階層を作成し、1 つのマネージャービューでナビゲーション バー全体を管理し、表示したいナビゲーション メニューの種類ごとに個別のビューを作成しました。ページ。

これが私の実装例です。

始める前に、closeBackbone の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;
    }

});

次に、特定のナビゲーション メニュー ビューをすべて拡張するベースビューを次に示します。それらはすべて同じtagNameclassNameidinitializeおよび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.SubNavBarrender新しいメニュービューで呼び出される関数があります
  • 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
    }
});

これらすべての利点は、メニュー固有のビューにイベントをアタッチできるようになったことです。ユーザーが別のコンテンツに移動してメニューが変更された場合、マネージャー ビューがそれらのバインドを解除します。

もちろん、ナビゲーション メニューを処理するために使用できるパターンは他にもたくさんありますが、うまくいけば、これがその道のりで役立つことを願っています。

于 2012-07-03T14:04:42.257 に答える
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();
    }
}

URL にセクションが含まれている場合は、ナビゲーション バーを追加してから、通常の方法を呼び出します。

于 2012-07-03T13:19:58.933 に答える