【问题标题】:How to delegate only the events from the active view in backbone?如何仅委托主干中活动视图中的事件?
【发布时间】:2013-10-31 14:17:00
【问题描述】:

我在 Backbone 中有两个视图。注册视图和登录视图。

登录视图

define(['text!templates/login.html'], function(loginTemplate) {
var loginView = Backbone.View.extend({
    el: $('#content'),

    events: {
        "submit form": "login"
    },

    login: function(e) {
        e.preventDefault();
        $.post('/user/login', {
                email: $('input.login-email').val(),
                password: $('input.login-password').val()
            }, function(data) {
                console.log(data);
            }).error(function(){
                $("#error").text('Unable to login.');
                $("#error").slideDown();
            });
    },

    render: function() {
        this.$el.html(loginTemplate);
    }
});

return new loginView;
});

注册查看

define(['text!templates/register.html'], function(registerTemplate) {
var registerView = Backbone.View.extend({
    el: $('#content'),

    events: {
        "submit form": "register"
    },

    register: function(e) {
        e.preventDefault();
        $.post('/user/register', {
            emailaddress: $("input.email").val(),
            password: $("input.password").val()
        }, function(data, textStatus, jqXHR) {
            console.log(data);
        });
    },

    render: function() {
        this.$el.html(registerTemplate);
        this.delegateEvents();
    }
});

return new registerView;
});

在切换到另一个视图之前,我取消了当前视图中的事件。但是主干视图模型在其构造函数中调用了 delegateEvent() 函数。因此,当我在浏览器中打开页面并获取登录视图并想要提交表单时,有两个请求,因为来自两个视图的事件都是委托的。我可以在构造函数中阻止 delegateEvent 函数吗?我知道,我可以使用 ID,而且我会使用,但我不喜欢“混乱”,我只想要来自活动视图的事件。

非常感谢。

编辑:这是我的路由器,也许它是我的“错误”的来源。

define(['views/register', 'views/login'], function(RegisterView, LoginView) {
var TestRouter = Backbone.Router.extend({
    currentView: null,
    routes: {
        "login": "login",
        "register": "register"
    },

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

    login: function() {
        this.changeView(LoginView);
    },

    register: function() {
        this.changeView(RegisterView);
    }
});

return new TestRouter;
});

【问题讨论】:

    标签: backbone.js backbone-views backbone-events


    【解决方案1】:

    这里的问题是您要手动声明 el 属性 (el: $('#content'))。

    在干净的代码中,您不想这样做。相反,您希望管理视图在路由器或父视图中动态插入的位置。像这样:

    var view = new registerView();
    view.render().$el.appendTo("#content");
    

    将布局与视图分开是非常重要的,这样可以使您的代码保持可维护性,并且不会遇到您遇到的问题。

    【讨论】:

    • 是的,这是一个很好的建议。但是,为什么这会影响代表团在构建时的观点呢?无论如何,这些视图都会在引导时构建,不是吗?
    • 是的,但委托将发生在其内部包装器 el(特定于上下文)上,而不是 #content(这是页面通用的)。
    • 你只需要一个空的div插入的div#content。请注意,您只关心您编写和维护的代码的“干净”HTML。动态 HTML 根本不重要,它不会改变你的生活,而且会让你的 JS 代码更易于维护。 “冗余” div 真的不是你应该关心的问题。
    • 可能有某种方式或某种方式的破解,但这会很脏,并使您的代码无法维护(或至少很难遵循)。您应该考虑 Backbone 最佳实践,并在此处简单地解决您的根本问题。
    • 如果你使用 Require.js 和 Backbone,你应该检查 Backbone-Boilerplate 项目。有一些相关的演示项目可以用来获取灵感。 github.com/backbone-boilerplate/backbone-boilerplate
    【解决方案2】:

    我的问题的解决方法是:

    当您没有在每个依赖项注入它们时构造所有视图时,它们没有被构造并且没有委托它们的事件。

    改变

    return new registerView;
    

    return registerView;
    

    在你看来。请注意 Simon Boudrias 的评论,不要在其中声明 views 元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      • 1970-01-01
      相关资源
      最近更新 更多