jQuery:为什么触发器不会从 JS 对象触发?

发布于 2024-09-25 02:46:53 字数 2880 浏览 6 评论 0原文

我一直在 jQuery 中实现一种发布者/订阅者设计模式。我基本上是利用 CoffeeScript 在 Javascript 中构建类,将其用作我的页面上的组件。即导航、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”是我想要触发的,但不幸的是我在这里没有运气。具有讽刺意味的是,我对另一个类做了完全相同的事情,该类以相同的方式调度自定义事件,并且侦听器接收它很好。关于为什么这行不通的任何想法?

更新:

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

I've been implementing a form of a publisher/subscriber design pattern in jQuery. I'm basically building classes in Javascript utilizing CoffeeScript that serve as components on my page. i.e. Navigation, DataList, etc.

Instead of having DOM elements fire events, I have instances of these classes that use trigger on themselves to send custom events. These instances can then listen to each other and can update the DOM elements they own accordingly based on the changes in each others behavior!

I know this works as I have one of my components dispatching a custom event properly. However, I've ran into a snag. I've created another component and for the life of me I cannot figure out why it's event is not being fired.

This is the implementation of my class:

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);

Pay attention to:

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

This code is triggered properly and returns the expected event type via an alert. But before the alert it is expected to trigger a custom event on itself. This is where I'm encountering my problem.

$(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);
}

You see here the alert "Hurray" is what I want to fire but unfortunately I am having no luck here. Ironically I've done the exact same thing with another class implemented the same way dispatching a custom event and the listener is receiving it just fine. Any ideas on why this wouldn't work?

Update:

Per discussing in the comments, it looks like Logging "this" in console returns the JS Object representing the class. But logging "$(this)" returns an empty jQuery object, thus trigger would never be fired. Any thoughts on why $(this) is coming up empty when "this" is accurately returning the instance of the class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

柳若烟 2024-10-02 02:46:53

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

I found out that jQuery could not index my object because the class implemented it's own version of a jQuery method. In this case, length(). Renaming the length() method to total() resolved the problem completely and any instance of the class can successfully trigger events.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文