Backbone.js 主干单击事件未在模板视图中触发
我正在开发一个基于动态模板的主干应用程序。我有一个页眉视图、侧面板视图和页脚视图,它们在调用任何其他视图时都会动态初始化。 问题是每个模板视图上都有未触发的事件。例如,我有一个按钮可以更改header视图中的语言,但它的事件没有触发 我的标题视图:Backbone.js 主干单击事件未在模板视图中触发,backbone.js,backbone-views,backbone-events,Backbone.js,Backbone Views,Backbone Events,我正在开发一个基于动态模板的主干应用程序。我有一个页眉视图、侧面板视图和页脚视图,它们在调用任何其他视图时都会动态初始化。 问题是每个模板视图上都有未触发的事件。例如,我有一个按钮可以更改header视图中的语言,但它的事件没有触发 我的标题视图: define([ "jquery", "backbone", "text!../../pages/header.html" ], function($, Backbone, headerTpl) { var header =
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")});
有没有办法解决这个问题。我需要知道如何触发这些事件,谢谢。事件处理程序不触发的原因是事件处理程序被委托给views元素,但您将模板附加到其他元素。由于目标元素位于该模板中,而该模板没有附加到视图的
el
,因此事件将永远不会冒泡到委托给它的处理程序中
除此之外,正如@mu太短所指出的,当您执行
$(parent.append)(this.template)时代码>,,
this.template
是模板函数。实际上,您应该使用数据调用它来获取模板。
您不应该使用像$(“”)
这样的全局选择器,而应该使用this.$el.find(“”)
作为最佳实践
另外,选项
仅在初始化
方法内部可用,在未定义
外部可用
不要将父对象传递到视图中,然后将其自身附加到父对象,而是在视图外部执行此操作,并使视图独立
最好在视图中声明属性,而不是在创建后添加属性
并且不需要手动将事件处理程序的上下文绑定到视图,默认情况下,事件处理程序的上下文将是视图
您的视图应该如下所示:
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\u container”).append(self.\u header.el)代码>
如果出于某种原因必须将父级作为选项传递到视图中,则应将其缓存在initialize
内的视图中,以便在其他地方引用它,如
this.parent = options.parent
旁注:
如您所见,我已经更改了您声明视图属性的顺序-initialize
,然后是template、event和render
我们初始化视图,创建模板函数,声明要委派的事件,然后呈现视图
您定义属性的顺序在内部并不重要,但是当其他开发人员查看您的代码时,它更容易理解。但是这是一个意见问题。(1)这个模板将是一个函数,而不是一段HTML。(2) 模板是什么样子的?This.template是一个使用文本库的html加载,您可以在require声明(1)中看到它
表示此.template
将是一个函数,而不是字符串。(2) 但是模板实际上是什么样子的呢?(3) 有时还使用parent
参数调用render
,有时不使用该参数,也会调用$('enBtn')
,而实际上应该使用this。$('enBtn'))
。我所说的模板是指不同的视图,每个视图都有自己的html,并且每次调用其他视图时都会加载这些视图。关于渲染函数,你是对的,我修复了它,并调用以显示正确的语言,正如你所看到的,我使用的是i18Thank,它可以工作,但它会将页眉添加到页面底部,而不会替换现有的页眉(我有两个标题,一个在页面顶部,一个在页面末尾,因为我们使用的是append,当我使用.html时,它只显示标题,其余的消失了)当我选择另一种语言时,有没有办法呈现整个页面。Thnx:)@ELKamel我不知道到底是什么问题。。但是,如果您希望页眉位于顶部而不是底部,请使用prepend()
而不是append()
。?不,这不是问题,问题是页眉可能会重复,而不是被替换。empty()不起作用