问题是为什么Backbone视图不执行jQuery自定义事件处理程序?
我试图在文本框中侦听回车键,当按下回车键时,只有回车键,我想执行一个功能。我使用require.js 2.1.15,jquery 1.11.1,骨干1.1.2和下划线1.7。
想法是注册" enter.js"用jquery插件。
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module depending on jQuery.
console.log("require.js registered");
define(['jquery'], factory);
} else {
// No AMD. Register plugin with global jQuery object.
console.log("no amd registered");
factory(jQuery);
}
}(function ($) {
console.log('registered event listener for input on the enter key');
$('input').keyup(function(e) {
console.log("key input");
if(e.keyCode == 13){
console.log("enter key assessed");
$(this).trigger('enter');
}
})
}));
这在控制台中执行并注册没有错误
require.js registered enter.js:12
registered event listener for input on the enter key Problem.js:4
现在是骨干代码:
define(function (require) {
"use strict";
console.log("start of ArithmeticView.js");
var
$ = require('jquery'),
enter = require('../../$plugins/enter'),
_ = require('underscore'),
Backbone = require('backbone'),
tpl = require('text!tpls/ArithmeticView.html'),
ProblemModels = require('../models/Problem'),
template = _.template(tpl);
return Backbone.View.extend( {
el: 'body',
events: {
"enter .answer": "solve",
},
initialize: function(){
this.render();
this.displayProblem();
},
render: function() {
console.log("render ArithmeticView");
return this.$el.html(template());
},
solve: function() {
console.log("solving ProblemModels.Problem");
var givenAnswer = $(".answer").val();
if(givenAnswer == this.problem.get("answer")) {
return this.displayProblem();
}
return this;
},
displayProblem: function() {
this.problem = new ProblemModels.Problem;
$('.problemArea').text(this.problem.get("question"));
return this;
}
});
});
当我在Chrome控制台中调试时,我可以看到附加到textarea的输入侦听器,并附加了类答案。我没有在控制台的任何地方看到jQuery插件中编码的实际功能代码。
答案 0 :(得分:1)
我完全理解您的规格,事实上我个人喜欢您处理“enter
”事件的方式。除了你实现它的方式之外,它永远不会用于动态加载HTML(思考模板)。
您的观点未收听“
enter
”事件的原因是因为不存在
是的,我知道,我知道。 enter.js插件绑定到所有<input>
元素。当时正在进行绑定的所有人都在那里。来自jQuery文档(强调他们的):
事件处理程序仅绑定到当前选定的元素;在您的代码调用
时,它们必须存在于页面上.on()
填充并附加模板代码时,_.template
将返回所有新的DOM元素。即使绑定到类似$('input').on
的类型的所有元素也不会保护性地绑定到新的<input>
元素。
在我看来,最好的办法是在渲染视图后重新绑定插件。
(通常你想使用委托来解决这个问题,并阅读插件中的jQuery.event.target
属性,看看按键是否来自<input>
元素,但你不能在您的视图events
哈希中使用它,因为Backbone无法检测委派。)
处理您需要监听的每种方法中的enter
按键。
只需替换
"enter .answer": "solve"
与
"keypress .answer": "solve"
并在solve
方法
solve: function(event) {
event.stopPropagation();
if (event.keyCode == 13) {
console.log("solving ProblemModels.Problem");
var givenAnswer = $(".answer").val();
if(givenAnswer == this.problem.get("answer")) {
return this.displayProblem();
}
return this;
}
}
Backbone将始终将jQuery event
对象发送到视图event
的回调。 jQuery打包keyCode
对象中的event
属性,该属性保存在keypress
事件中检测到的密钥。在你的情况下(如果你看你的插件)我们所做的就是测试按下的键是否是回车键,键码为13。
上面重现了您想要的效果,没有注册的复杂性,然后使用Require将插件加载到范围内。我知道它不像使用enter.js
插件那样整齐地封装,但它使代码更简单,并且可能在没有插件开销的情况下运行更精简。