1

require.jsを使用するバックボーンアプリケーションを開発しています。

ユーザーがモデルの「id」を入力し、そのモデルが存在する場合はそのビューにリダイレクトされるか、存在しない場合はエラーメッセージを表示するようにします。これは非常に単純に聞こえますが、各コンポーネントの役割を理解するのに苦労しています。

以下のアプリケーションでは、ユーザーは入力(ID'modelId')とボタン(クラス属性'lookup')のあるインデックスページにアクセスします。

次のコードはルーターです。

define(['views/index', 'views/myModelView', 'models/myModel'], 
    function(IndexView, MyModelView, myModel) {
    var MyRouter = Backbone.Router.extend({
        currentView: null,

        routes: {
            "index": "index",
            "view/:id": "view"
        },

        changeView: function(view) {
            if(null != this.currentView) {
                this.currentView.undelegateEvents();
            }
            this.currentView = view;
            this.currentView.render();
        },

        index: function() {
            this.changeView(new IndexView());
        },

        view: function(id) {
            //OBTAIN MODEL HERE?
            //var model
            roter.changeView(new MyModelView(model))
        }

    });

    return new MyRouter();
});

次のコードはインデックスビューです

define(['text!templates/index.html', 'models/myModel'], 
    function( indexTemplate, MyModel) {
    var indexView = Backbone.View.extend({
        el: $('#content'),

        events: {
            "click .lookup": "lookup"
        },

        render: function() {
            this.$el.html(indexTemplate);
            $("#error").hide();
        },

        lookup: function(){
            var modelId = $("#modelId").val()
            var model = new MyModel({id:modelId});
            model.fetch({
                success: function(){
                    window.location.hash = 'view/'+model.id;
                },
                error: function(){
                    $("#error").text('Cannot view model');
                    $("#error").slideDown();
                }
            });
        },
    });
    return indexView
});

私が理解できないのは、インデックスビューでモデルを検索する方が良いオプションのように思われることです(したがって、ユーザーが存在しないモデルを要求した場合にエラーメッセージを表示し、保持することもできます)ルータークリーナー)。ただし、問題は、view /:idルーターがトリガーされたときに、ルーターがモデルを参照しないようになったことです。view()関数でモデルを取得するにはどうすればよいですか?

別のフェッチを実行できると思いますが、それは冗長で間違っているようです。または、ルーターとビューの両方が共有する(インデックスビューがモデルを配置できる)グローバルオブジェクトがあるはずですが、それは密結合のようです。

4

1 に答える 1

2

このようなことができます。モデルの代わりにコレクションで同様のことを行うことができますが、コレクション全体を取得/表示したくないようですか?

このタイプのソリューション (@mpm が提案していたものと同様だと思います) を使用すると、アプリはブラウザーの更新、前後のナビゲーションを適切に処理します。基本的には MainView があり、実際にはアプリ コントローラーのように機能します。これは、ルーターまたはユーザーの操作 (アイテム ビューでルックアップまたは [インデックスに戻る] ボタンをクリック) によってトリガーされたイベントを処理します。

これらのアイデアの多くは、Derick Bailey のおかげです

ルーターで。これらは、ユーザーが URL を変更したり、前後に移動したりしてナビゲートした場合にのみトリガーされるようになりました。

    index: function() {
        Backbone.trigger('show-lookup-view');
    },

    view: function(id) {
        var model = new MyModel({id: id});
        model.fetch({
            success: function(){
                Backbone.trigger('show-item-view', model);
            },
            error: function(){
                // user could have typed in an invalid URL, do something here,
                // or just make the ItemView handle an invalid model and show that view...
            }
        });
    }

ルーターではなく、アプリの起動時に作成する新しい MainView では、次のようになります。

el: 'body',

initialize: function (options) {
    this.router = options.router;

    // listen for events, either from the router or some view.
    this.listenTo(Backbone, 'show-lookup-view', this.showLookup);
    this.listenTo(Backbone, 'show-item-view', this.showItem);
},

changeView: function(view) {
    if(null != this.currentView) {
       // remove() instead of undelegateEvents() here
       this.currentView.remove();
    }
    this.currentView = view;
    this.$el.html(view.render().el);
},

showLookup: function(){
    var view = new IndexView();
    this.changeView(view);
    // note this does not trigger the route, only changes hash.
    // this ensures your URL is right, and if it was already #index because
    // this was triggered by the router, it has no effect.
    this.router.navigate('index'); 
},

showItem: function(model){
    var view = new ItemView({model: model});
    this.changeView(view);
    this.router.navigate('items/' + model.id); 
}

次に、IndexView で、既に取得したモデルで「show-item-view」イベントをトリガーします。

    lookup: function(){
        var modelId = $("#modelId").val()
        var model = new MyModel({id:modelId});
        model.fetch({
            success: function(){
                Backbone.trigger('show-item-view', model);
            },
            error: function(){
                $("#error").text('Cannot view model');
                $("#error").slideDown();
            }
        });
    },

これが完璧とは思いませんが、良い方向に向かうことを願っています。

于 2013-02-16T03:08:23.000 に答える