骨干视图,模型和路由器的角色

时间:2013-02-16 02:11:10

标签: backbone.js requirejs

我正在开发一个使用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()函数中获取模型?

我想它可以做另一次获取,但这看起来多余而且错误。或者可能有一些全局对象,路由器和视图共享(索引视图可以放入模型),但这似乎是紧耦合。

1 个答案:

答案 0 :(得分:2)

你可以这样做。您可以使用集合而不是模型执行类似的操作,但似乎您不想获取/显示整个集合?

使用这种类型的解决方案(我认为类似于@mpm的建议),您的应用将正确处理浏览器刷新,后退/前进导航。你基本上有一个MainView,它真的更像是一个app控制器。它处理由路由器或用户交互(单击项目视图上的查找或返回索引按钮)触发的事件。

很多这些想法都归功于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();
            }
        });
    },

我不认为这完全是完美的,但我希望它可以指出你的方向。