javascript - Jquery 观察者模式

标签 javascript jquery observer-pattern

我一直在互联网上寻找在 jquery 中实现观察者模式的示例。

我想要这样

observer1.observe(subject);
observer2.observe(subject);

为观察者定义一些自定义事件回调

observer1.bind('customEvent', function(contextData) {
  //Some code
});
observer1.bind('anotherCustomEvent', function(contextData) {
  //Some code  
});
observer2.bind('customEvent', function(contextData) {
  //Some code  
});

下面的行将触发两个观察者的 customEvent 回调

subject.trigger('customEvent', contextData);

而下面的代码只会在 observer1 上触发 anotherCustomEvent,因为 observer2 没有绑定(bind)该自定义事件

subject.trigger('anotherCustomEvent', contextData);

互联网上的指南更笼统:

$( document ).on( "topicName" , function () {
  //..perform some behaviour
});

$( document ).trigger( "topicName" );

(示例来自 http://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjquery) 我看不出如何使用上面的代码来完成我正在寻找的东西。

要么我必须这样做(如果我像上面的例子一样保持它):

$(document).on("customEvent", function () {
  observer1.trigger("customEvent");
  observer2.trigger("customEvent");
});

$(subject).click(function() { 
  $(document).trigger("customEvent");
});

或者更好一点:

$(subject).click(function() { 
  observer1.trigger("customEvent");
  observer2.trigger("customEvent");
});

无论哪种方式,我都不得不编辑 subject-click-callback 或 document-customEvent-callback,而不是告诉观察者订阅主题。

我是不是误解了观察者模式,或者有没有办法实现我正在寻找的东西?

http://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjavascript在该章的后面提到发布/订阅模式。这对我来说可能是一种方式,但我缺少示例背后的代码。

最佳答案

来自您的评论:

I just can't see how this is achieved when you have to tell the subject which elements to trigger by selectors instead of the subject having a list that the observer can register to

如果我错了请纠正我,但您似乎误解了该模式是如何在 jQuery 中实现的。您不会“告诉主题触发哪些元素”,主题也没有“观察者可以注册的列表”。它是这样工作的:

  • 主题/发布者发出/触发某些事件(在您定义的某些情况下)。
  • 观察者/订阅者监听某些事件。它保留它订阅的事件列表。
  • 这都是基于 DOM 事件的,因此受到 DOM 事件模型的限制。

例如,考虑以下 HTML:

<div id="div1">div 1</div>
<div id="div2">div 2</div>

让我们让内部 div 触发一个名为 'custom' 的自定义事件。您定义什么时候应该发生,在这个例子中,这将在他们被点击时发生:

$('div').on('click', function(e) {
    $(this).trigger('custom');
});

现在让 document 元素订阅该自定义事件:

$(document).on('custom', function(e) {
    console.log('document is handling custom event triggered by ' + e.target.id);
});

当自定义事件被其中一个 div 触发时,观察者/订阅者会收到通知,并将一条消息记录到控制台。

该示例使用 document 作为观察者是有原因的:事件在 DOM 树中向上冒泡,并且只能被触发它的元素的祖先元素捕获。由于 document 是 DOM 树的根,它可以看到所有事件。如果 #div1 是我们的观察者,它只会看到由 #div1 本身触发的事件,而不会看到由 #div2 触发的事件。

也许这个限制让您感到困惑?


有一些方法可以规避该限制,但通常情况下,如果您想根据 #div2 触发的事件对 #div1 执行某些操作,您只需这样做从您在 document 元素(或最接近两个 div 的共同祖先)上设置的回调中。无论如何,您似乎真的想要一个替代方案,所以这里有一个 jQuery 插件形式的替代方案:

$.fn.observe = function(eventName, callback) {
    return this.each(function(){
        var el = this;
        $(document).on(eventName, function(){
            callback.apply(el, arguments);
        })
    });
}

你可以这样使用它:

$('#div1').observe('custom', function(e) {
    // do something
});

实例:http://jsfiddle.net/JwJsP/1

关于javascript - Jquery 观察者模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12590091/

相关文章:

javascript - 如何将一段文本转换为父子 JSON 文件?

javascript - 幻灯片过渡 - Javascript

javascript - 如何使用 jquery 更改按键组合的样式表?

javascript - 加载时隐藏 ul 元素,点击时显示

java - 观察者设计模式

Java观察者模式寻找发件人?

使用 Selenium Web 驱动程序从网站获取隐藏文本值的 Javascript

jquery - JQGrid 获取特定列的所有值,而不考虑分页

Java Observer/Observable 模式不通知

javascript - AngularJS 聚焦元素