jquery自定义事件不在骨干中工作

时间:2014-12-23 03:34:44

标签: backbone.js jquery-events

问题是为什么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插件中编码的实际功能代码。

1 个答案:

答案 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插件那样整齐地封装,但它使代码更简单,并且可能在没有插件开销的情况下运行更精简。