骨干点击事件未在模板视图中触发

时间:2015-11-26 22:40:10

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

我正在开发一个基于动态模板的Backbone应用程序。我有一个标题视图,侧面板视图和页脚视图,在调用任何其他视图时动态初始化。 问题是我在每个模板视图上都有未触发的事件。例如,我有一个按钮,用于更改标题视图中的语言,但其事件未触发。

我的标题查看:

define([ "jquery", "backbone", "text!../../pages/header.html" ], function($,
        Backbone, headerTpl) {

    var header = Backbone.View.extend({
        events : {
            "click #enBtn":"swichToEnglish",
             "click #frBtn":"swichToFrench"
        },
        initialize : function(options) {
             _.bindAll(this, "swichToFrench","swichToEnglish");

            this.render(options.parent);
            //$("#enBtn").css("pointer-events","none");

        },
        render : function(parent) {
            this.template = _.template(headerTpl);
            $(parent).append(this.template);
            return this;
        },
        swichToFrench:function(){
            console.log("switch to frensh");
            if(i18n.currentLocal == 'en'){
                i18n.currentLocal='fr';
                $("#frBtn").css("pointer-events","auto");
                this.render(options.parent);
        }
        },
        swichToEnglish:function(){
            console.log("switch to English");
            if(i18n.currentLocal == 'fr'){
                i18n.currentLocal='en';
                $("#enBtn").css("pointer-events","auto");
                $("#frBtn").css("pointer-events","none");
                this.render(options.parent);
        }   
        }
    });

    return header;
});

在路由器中调用标题视图:

self._header = new Header({parent: $(".main_container")});

如何解决此问题的任何想法。我需要知道如何解雇这些事件谢谢。

1 个答案:

答案 0 :(得分:5)

事件处理程序未触发的原因是因为事件处理程序被委托给views元素,但您将模板附加到其他元素。由于目标元素位于此模板中,而该模板未附加到视图el,因此事件将永远不会进入委托给它的处理程序。

除此之外,由于@mu太短指出,当你$(parent).append(this.template);时, this.template是模板函数。您实际应该使用数据调用它来获取模板。 并且您不应该使用$('')等全局选择器,而应使用this.$el.find('')作为最佳做法。

另外,options仅在initialize方法中可用,并且在undefined之外。

不是将父级传递给视图,然后将其自身附加到父级,而是在视图外部进行,并使视图独立。

同时在视图中声明template属性,而不是在创建后将其添加为最佳做法。

并且不需要手动将事件处理程序的上下文绑定到视图,默认情况下,事件处理程序的上下文将是视图。

您的观点应如下所示:

define([ "jquery", "backbone", "text!../../pages/header.html" ], function($,
    Backbone, headerTpl) {

  var header = Backbone.View.extend({
    initialize : function(options) {
        this.render();
    },
    template: _.template(headerTpl),
    events : {
        "click #enBtn":"swichToEnglish",
        "click #frBtn":"swichToFrench"
    },
    render : function() {
        this.$el.append(this.template(/* pass the data here*/));
     //--------^----- this is required for the events to work
        return this;
    },
    swichToFrench:function(){
        if(i18n.currentLocal == 'en'){
            i18n.currentLocal='fr';
            this.$el.find("#frBtn").css("pointer-events","auto");
            this.render();
        }
    },
    swichToEnglish:function(){
        if(i18n.currentLocal == 'fr'){
          i18n.currentLocal='en';
          this.$el.find("#enBtn").css("pointer-events","auto");
          this.$el.find("#frBtn").css("pointer-events","none");
          this.render();
      }   
    }
  });

  return header;
});

您可以创建如下:

self._header = new Header();
$(".main_container").append(self._header.el);

看起来您只想将视图内容添加到'.main_container',并且不需要其他元素。在这种情况下,您可以将您的观看次数el指向它,而不是通过将其作为el传递给以下选项来创建新元素:

self._header = new Header({
 el: '.main_container' // this.el will refer to `.main_container` in view
});

那么你不必做$(".main_container").append(self._header.el);

如果由于某种原因必须将父级作为选项传递给视图,那么您应该将其缓存在initialize内的视图中,以便您可以将其引用到其他地方,例如。

this.parent = options.parent

旁注:

正如您所看到的,我已经更改了您声明视图属性的顺序 - initialize位于顶部,然后是模板,事件和渲染。

我们初始化视图,创建模板函数,声明要委托的事件,然后渲染视图。

您定义属性的顺序在内部并不重要,但当其他开发人员查看您的代码时,它更容易消化。但这是一个意见问题。

相关问题