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 回答