【问题标题】:jQuery: Why would trigger not fire from a JS object?jQuery:为什么触发器不会从 JS 对象触发?
【发布时间】:2011-04-17 21:37:22
【问题描述】:

我一直在 jQuery 中实现一种发布者/订阅者设计模式。我基本上是使用作为我页面上的组件的 CoffeeScript 在 Javascript 中构建类。即Navigation、DataList等

我没有让 DOM 元素触发事件,而是有这些类的实例,它们在自身上使用触发器来发送自定义事件。然后这些实例可以互相监听,并可以根据彼此行为的变化相应地更新它们拥有的 DOM 元素!

我知道这是可行的,因为我的一个组件可以正确调度自定义事件。然而,我遇到了障碍。我创建了另一个组件,但在我的一生中,我无法弄清楚为什么它的事件没有被触发。

这是我的类的实现:

window.List = (function() {
    List = function(element, settings) {
      var _a, _b, _c;
      this.list = $(element);
      this.settings = jQuery.extend(List.DEFAULTS, settings);
      this.links = this.list.find(this.settings.link_selector);
      this.links.selectable();
      _b = [SelectableEvent.COMPLETED, SelectableEvent.UNDONE, SelectableEvent.SELECTED, SelectableEvent.DESELECTED];
      for (_a = 0, _c = _b.length; _a < _c; _a++) {
        (function() {
          var event_type = _b[_a];
          return this.links.bind(event_type, __bind(function(event, selectable_event) {
            return this.dispatch(selectable_event);
          }, this));
        }).call(this);
      }
      return this;
    };
    List.DEFAULTS = {
      link_selector: "a",
      completed_selector: ".completed"
    };
    List.prototype.change = function(mode, previous_mode) {
      if (mode !== this.mode) {
        this.mode = mode;
        if (previous_mode) {
          this.list.removeClass(previous_mode);
        }
        return this.list.addClass(this.mode);
      }
    };
    List.prototype.length = function() {
      return this.links.length;
    };
    List.prototype.remaining = function() {
      return this.length() - this.list.find(this.settings.completed_selector).length;
    };
    List.prototype.dispatch = function(selectable_event) {
      $(this).trigger(selectable_event.type, selectable_event);
      return alert(selectable_event.type);
    };
    return List;
}).call(this);

注意:

List.prototype.dispatch = function(selectable_event) {
    $(this).trigger(selectable_event.type, selectable_event);
    return alert(selectable_event.type);
};

此代码被正确触发并通过警报返回预期的事件类型。但在警报之前,预计它会触发自身的自定义事件。这就是我遇到问题的地方。

$(document).ready(function() {
    var list_change_handler, todo_list;
    todo_list = new List("ul.tasks");
    list_change_handler = function(event, selectable_event) {
      return alert("Hurray!");
    };
    $(todo_list).bind(SelectableEvent.COMPLETED, list_change_handler);
    $(todo_list).bind(SelectableEvent.UNDONE, list_change_handler);
    $(todo_list).bind(SelectableEvent.SELECTED, list_change_handler);
    $(todo_list).bind(SelectableEvent.DESELECTED, list_change_handler);
}

你在这里看到警报“Hurray”是我想要触发的,但不幸的是我在这里没有运气。具有讽刺意味的是,我对另一个类执行了完全相同的操作,该类以相同的方式实现了分派自定义事件,并且侦听器很好地接收了它。关于为什么这不起作用的任何想法?

更新:

根据 cmets 中的讨论,看起来在控制台中记录“this”会返回代表该类的 JS 对象。但是记录 "$(this)" 返回一个空的 jQuery 对象,因此触发器永远不会被触发。当“this”准确地返回类的实例时,为什么 $(this) 会为空?

【问题讨论】:

  • 使用var来声明你的局部变量!!!!!!
  • 这是来自 CoffeeScript 的生成器。这是一个很好的收获。我不确定为什么在某些情况下不是。它通常在任何地方都这样做。几周前,我最近升级到了更新版本的编译器。也许这个问题已经解决了。
  • 抱歉,我没有粘贴到整个文档中。ready()
  • 好吧,我看到“列表”代码具有适当的var,但“就绪”处理程序没有。如果您设置其中两个,并且每个都使用相同的变量名,那么这将是一个问题。
  • 这里我简化了准备并重新编译。所有的变量都在 ready 函数的第一行。 Coffee 会自动确定变量的范围,因此这应该不是问题。我只是忘了在函数的第一行复制。

标签: javascript jquery coffeescript dom-events


【解决方案1】:

我发现 jQuery 无法索引我的对象,因为该类实现了它自己的 jQuery 方法版本。在这种情况下,长度()。将 length() 方法重命名为 total() 彻底解决了问题,类的任何实例都可以成功触发事件。

【讨论】:

  • 很有趣,而且很有发现。让我想起了经典的 IE 弱点:为按钮提供 ID“提交”
猜你喜欢
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
相关资源
最近更新 更多