【问题标题】:Passing control back to a Backbone Router from a view?将控制权从视图传递回骨干路由器?
【发布时间】:2014-10-16 22:13:49
【问题描述】:

我有一个登录视图和它的登录模型。 loginmodel 是从主路由器的初始化创建的。这种方式根据loginmodel的loginp属性mainrouter的render_home决定是渲染homeview还是导航到调用render_login的登录路由。 render_login 有一个方法来save() 从登录视图的输入字段填充的登录模型。所以如果save()响应的数据是正确的并且loginmodel改变了,它的loginp属性就变为true。所以现在应该渲染主视图。但我无法成功。

我认为此时应该将控制权传递回主路由器的路由,该路由再次调用上面的render_home。所以它测试loginView.model.get('loginp') == true 并结果为true,所以这次创建homeview 并通过已经在homeview 中定义的homeView.render() 呈现它。

我在登录视图中放置了一个listenTo,用于当它的模型更改或同步时调用mainrouter中的路由来调用render_home。但这以这两个视图之间无休止的来回结束而没有任何渲染。 this.listenTo( this.loginView.model, 'sync', Backbone.history.navigate("",{trigger:true}));

路由""顺便分配给render_home

我错过了什么。不能将控制权交还给路由器吗? 主路由器:

define([
    'jquery',
    'ratchet',
    'underscore',
    'backbone',

    'login/loginmodel',

    'login/loginview',
    'register/registerview',

    'home/homeview',
    ],
    function($, Ratchet, _, Backbone, LoginModel, LoginView, RegisterView, HomeView){
        var MainRouter = Backbone.Router.extend({
            routes: {
                "": "render_home",

                "login": "render_login",
                "register": "render_register"
            },

            initialize: function(){
                this.loginView = new LoginView;                 
            },

            render_home: function(){                    
                this.loginView.model.fetch({
                    success: function(model){
                        if( model.get('loginp') == true ){ //show you app view for logged in users!
                            this.homeView = new HomeView();
                            this.homeView.render();
                        }
                        else { //not logged in!
                            Backbone.history.navigate("/login", {trigger:true})
                        }
                    },
                });

            },
            render_login: function(){ //display your login view
                this.loginView.render();

            },
            render_register: function(){ //display your register view
                this.registerView = new RegisterView;                   
                this.registerView.render();
            },
        });

        return MainRouter;
});

登录查看:

    define([
    'jquery',
    'ratchet',
    'underscore',
    'backbone',

    'login/loginmodel',
    'text!login/logintemplate.html',

    ],
    function($, Ratchet, _, Backbone, LoginModel, LoginTemplate){
        var LoginView = Backbone.View.extend({

            el: $('body'),

            initialize: function(){
                this.model = new LoginModel;
            },

            template: _.template( LoginTemplate ),

            render: function(){ //display your login view
                this.$el.html( this.template( this.model.attributes ) );
            },

            events: {
                'keyup input' : 'updateform',
                'click #loginbutton' : 'login',
                'click #renderregisterbutton' : 'render_register',
            },

            updateform: function(e){
                var el = e.target;
                var formData = {};
                formData[ el.id ] = $(el).val();
                this.model.set( formData );
            },

            login: function(e){
                e.preventDefault();
                this.model.save();
                console.log( JSON.stringify( this.model ) );
            },

            render_register: function(){
                Backbone.history.navigate("/register", {trigger:true});
            },
        });

        return LoginView;
});

登录模型:

define([
    'underscore',
    'backbone',
    ],
    function(_, Backbone) {
        var LoginModel = Backbone.Model.extend({

            urlRoot: '/log_in',

            defaults: {
                username: null,
            },
        });

        return LoginModel;
});

【问题讨论】:

    标签: javascript backbone.js


    【解决方案1】:

    您绝对可以将控制权从Route“传递”到View 并返回;您的 render_login 函数正是这样做的:

    render_login: function(){ //display your login view
        // 1) router has control
        this.loginView.render(); // 2) control passes to loginView
        // 3) control passes back to the router
    },
    

    但这仅适用于 同步 逻辑。我认为您遇到的问题是因为您在 render_home 方法中使用了 asynchronous 逻辑 (this.loginView.model.fetch())。异步逻辑从主执行路径中分离出来,所以render_home 的路径更像:

    // 0) Router has control, and calls render_home
    render_home: function(){
        // 1) LoginView has control
        this.loginView.model.fetch({
            success: function(model){
                // 4) LoginView has control once again, but now routing is done
                if( model.get('loginp') == true ){ //show you app view for logged in users!
                    this.homeView = new HomeView();
                    this.homeView.render();
                }
                else { //not logged in!
                    Backbone.history.navigate("/login", {trigger:true})
                }
            },
        });
        // 2) LoginView still has control
    },
    // 3) Control passes back to the Router, which finishes routing
    

    所以,当fetch 返回时,没有路由逻辑可以返回。

    但是,这很容易解决:只需从您的fetch 成功处理程序中调用Backbone.history.navigate(使用trigger: true)。这将启动一个新的路由过程,到那时(因为 fetch 已经完成)LoginModel 现在将被填充并且您的路由逻辑应该可以工作。

    【讨论】:

    • 感谢您的回复。它给了我关于控制传球的见解。当我添加了您建议的导航时,它会导致两个视图之间来回无休止。现在我已经解决了。当我完成时,我会写。它在路由器中包含this.listenTo( this.loginView.model, 'change', this.render_home );//this solved render_home problem.
    • 啊,抱歉,我的解决方案“开箱即用”不起作用(有时,如果没有 IDE/测试环境,很难为 StackOverflow 编写代码)。当您获得最终解决方案时,您可以:A)将其作为单独的答案发布,B)编辑我的答案并添加新代码,或 C)(如果您没有编辑权限)将新代码添加为评论我很乐意用它来更新我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多