【问题标题】:jquery custom event not working in backbonejquery自定义事件在主干中不起作用
【发布时间】:2014-12-23 03:34:43
【问题描述】:

问题是为什么 Backbone 视图不执行 jQuery 自定义事件处理程序?

我正在尝试侦听文本框中的回车键,当按下回车键时,只有回车键,我想执行一个功能。我正在使用 require.js 2.1.15、jquery 1.11.1、主干 1.1.2 和下划线 1.7。

想法是用jquery注册“enter.js”插件。

(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 插件中编码的实际功能代码。

【问题讨论】:

  • 尝试将textarea 更改为inputenter.jsinputs 上注册keyup。

标签: backbone.js jquery-events


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

【讨论】:

  • 这个解决方案将事件处理与解决功能联系起来,而我想离开解决来检查用户给出的问题解决方案的答案。
    您的回答确实加快了单个用例的速度,但它不允许我处理输入事件,也不允许我只执行有问题的功能。提供答案后,函数需要知道它是如何被触发的。不是首选。
  • 因此,在视图未侦听“输入”事件的情况下处理您提供给我的信息是因为它不存在。所以我只是将触发 'enter' 事件的 'enter' 监听器添加到视图中它自己的函数中,并在渲染函数之后从初始化中调用它。完美运行。感谢您的见解。
  • 没问题。很高兴为您提供帮助!
猜你喜欢
  • 2023-04-02
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 2014-06-01
  • 2023-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多