jQuery中的自定义事件?

Custom events in jQuery?

我正在寻找一些关于如何以最佳方式在jquery中实现自定义事件处理的输入。我知道如何从dom元素(如click)连接事件,但是我正在构建一个小的javascript库/插件来处理一些预览功能。

我运行了一个脚本,从我得到的一组规则和数据/用户输入中更新dom元素中的一些文本,但现在我需要在其他元素中显示这个脚本不可能知道的相同文本。我需要的是一个好的模式,以某种方式观察生成所需文本的脚本。

那我该怎么做呢?我是否忽略了jquery中的一些内置功能来引发/处理用户事件,或者是否需要一些jquery插件来完成这项工作?您认为处理这个问题的最佳方法/插件是什么?


接受答案中提供的链接显示了使用jquery实现pub/sub系统的一种很好的方法,但我发现代码有点难以阅读,因此下面是我的代码简化版本:

http://jsfiddle.net/tfw89/5/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$(document).on('testEvent', function(e, eventInfo) {
  subscribers = $('.subscribers-testEvent');
  subscribers.trigger('testEventHandler', [eventInfo]);
});

$('#myButton').on('click', function() {
  $(document).trigger('testEvent', [1011]);
});

$('#notifier1').on('testEventHandler', function(e, eventInfo) {
  alert('(notifier1)The value of eventInfo is: ' + eventInfo);
});

$('#notifier2').on('testEventHandler', function(e, eventInfo) {
  alert('(notifier2)The value of eventInfo is: ' + eventInfo);
});


看看这个:

(从过期的博客页面http://jamiethompson.co.uk/web/2008/06/17/publish-subscribe-with-jquery/based on the archived version at http://web.archive.org/web/20130120010146/http://jamiethompson.co.uk/web/2008/06/17/publish subscribe with jquery/)重新打印)

使用jquery发布/订阅

2008年6月17日

为了编写一个集成了GoogleGears离线功能的jquery用户界面,我一直在玩弄一些代码,用jquery来轮询网络连接状态。

网络检测对象

基本前提很简单。我们创建一个网络检测对象的实例,它将定期轮询一个URL。如果这些HTTP请求失败,我们可以假定网络连接已丢失,或者服务器当前无法访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$.networkDetection = function(url,interval){
    var url = url;
    var interval = interval;
    online = false;
    this.StartPolling = function(){
        this.StopPolling();
        this.timer = setInterval(poll, interval);
    };
    this.StopPolling = function(){
        clearInterval(this.timer);
    };
    this.setPollInterval= function(i) {
        interval = i;
    };
    this.getOnlineStatus = function(){
        return online;
    };
    function poll() {
        $.ajax({
            type:"POST",
            url: url,
            dataType:"text",
            error: function(){
                online = false;
                $(document).trigger('status.networkDetection',[false]);
            },
            success: function(){
                online = true;
                $(document).trigger('status.networkDetection',[true]);
            }
        });
    };
};

您可以在这里查看演示。将浏览器设置为脱机工作,然后查看会发生什么…不,不是很刺激。

触发和绑定

令人兴奋的是(或者至少是让我兴奋的是)状态通过应用程序进行中继的方法。我偶然发现了一种很大程度上没有讨论过的方法,即使用jquery的触发器和绑定方法来实现pub/sub系统。

演示代码比需要的要迟钝。网络检测对象将"状态"事件发布到文档中,文档会主动侦听这些事件,然后将"通知"事件发布到所有订阅服务器(稍后将详细介绍这些订阅服务器)。这背后的理由是,在现实世界的应用程序中,可能会有更多的逻辑控制"通知"事件的发布时间和方式。

1
2
3
4
5
6
7
8
9
10
11
$(document).bind("status.networkDetection", function(e, status){
    // subscribers can be namespaced with multiple classes
    subscribers = $('.subscriber.networkDetection');
    // publish notify.networkDetection even to subscribers
    subscribers.trigger("notify.networkDetection", [status])
    /*
    other logic based on network connectivity could go here
    use google gears offline storage etc
    maybe trigger some other events
    */
});

由于jquery以DOM为中心的方法,事件被发布到(触发)DOM元素。这可以是常规事件的窗口或文档对象,也可以使用选择器生成jquery对象。我在演示中采用的方法是创建一种几乎命名的方法来定义订阅服务器。

将要成为订户的DOM元素简单地用"subscriber"和"networkdetection"分类。然后,通过在$(".subscriber.networkDetection")上触发一个notify事件,我们只能将事件发布到这些元素(演示中只有一个元素)。

#notifierdiv是.subscriber.networkDetection组订户的一部分,它有一个绑定到它的匿名函数,有效地充当监听器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$('#notifier').bind("notify.networkDetection",function(e, online){
    // the following simply demonstrates
    notifier = $(this);
    if(online){
        if (!notifier.hasClass("online")){
            $(this)
                .addClass("online")
                .removeClass("offline")
                .text("ONLINE");
        }
    }else{
        if (!notifier.hasClass("offline")){
            $(this)
                .addClass("offline")
                .removeClass("online")
                .text("OFFLINE");
        }
    };
});

好了,给你。这一切都很冗长,我的例子一点也不令人兴奋。它也没有展示你可以用这些方法做的任何有趣的事情,但是如果有人对挖掘源代码感兴趣的话,请放心。所有代码都在演示页面的头中


我认为是这样。。可以"绑定"自定义事件,例如(来自:http://docs.jquery.com/events/bind typedatafn):

1
2
3
4
5
6
7
8
9
 $("p").bind("myCustomEvent", function(e, myName, myValue){
      $(this).text(myName +", hi there!");
      $("span").stop().css("opacity", 1)
               .text("myName =" + myName)
               .fadeIn(30).fadeOut(1000);
    });
    $("button").click(function () {
      $("p").trigger("myCustomEvent", ["John" ]);
    });


我有一个类似的问题,但实际上是在寻找一个不同的答案;我正在创建一个自定义事件。例如,不要总是这样说:

1
2
3
4
5
6
$('#myInput').keydown(function(ev) {
    if (ev.which == 13) {
        ev.preventDefault();
        // Do some stuff that handles the enter key
    }
});

我想把它缩写为:

1
2
3
$('#myInput').enterKey(function() {
    // Do some stuff that handles the enter key
});

触发器和绑定并不能说明全部情况-这是一个jquery插件。http://docs.jquery.com/plugins/authoring/编辑

"enterkey"函数作为属性附加到jquery.fn-这是所需的代码:

1
2
3
4
5
6
7
8
9
10
11
12
(function($){
    $('body').on('keydown', 'input', function(ev) {
        if (ev.which == 13) {
            var enterEv = $.extend({}, ev, { type: 'enterKey' });
            return $(ev.target).trigger(enterEv);
        }
    });

    $.fn.enterKey = function(selector, data, fn) {
        return this.on('enterKey', selector, data, fn);
    };
})(jQuery);

http://jsfiddle.net/b9chris/ckvuj/4/

上面的一个细节是,您可以在链接侦听器上优雅地处理键盘输入,例如:

1
2
3
4
$('a.button').on('click enterKey', function(ev) {
    ev.preventDefault();
    ...
});

编辑:更新后将正确的this上下文传递给处理程序,并将处理程序返回的任何返回值返回到jquery(例如,在您希望取消事件和冒泡的情况下)。更新以将适当的jquery事件对象传递给处理程序,包括键代码和取消事件的能力。

旧jspiddle:http://jsfiddle.net/b9chris/vweb9/24/


这是一篇旧文章,但我会尝试用新信息更新它。

要使用自定义事件,需要将其绑定到某个DOM元素并触发它。所以你需要使用

.on() method takes an event type and an event handling function as
arguments. Optionally, it can also receive event-related data as its
second argument, pushing the event handling function to the third
argument. Any data that is passed will be available to the event
handling function in the data property of the event object. The event
handling function always receives the event object as its first
argument.

.trigger() method takes an event type as its argument. Optionally, it
can also take an array of values. These values will be passed to the
event handling function as arguments after the event object.

代码如下:

1
2
3
4
5
6
7
8
9
10
$(document).on("getMsg", {
    msg:"Hello to everyone",
    time: new Date()
}, function(e, param) {
    console.log( e.data.msg );
    console.log( e.data.time );
    console.log( param );
});

$( document ).trigger("getMsg", ["Hello guys"] );

这里和这里都能找到很好的解释。为什么这确实有用?我在这个来自Twitter工程师的精彩解释中找到了如何使用它。

另外,在简单的javascript中,您可以使用新的customvent来实现这一点,但是要注意IE和Safari问题。


以下是我如何编写自定义事件:

1
2
var event = jQuery.Event('customEventName);
$(element).trigger(event);

当然,你可以这么做

1
$(element).trigger('eventname');

但是我写的方法允许您通过执行以下操作来检测用户是否阻止了默认值

1
var prevented = event.isDefaultPrevented();

这允许您听取最终用户停止处理特定事件的请求,例如,如果单击表单中的按钮元素,但不希望在出现错误时发布表单。

我通常听这样的活动

1
2
3
$(element).off('eventname.namespace').on('eventname.namespace', function () {
    ...
});

再一次,你可以

1
2
3
$(element).on('eventname', function () {
    ...
});

但我一直觉得这有点不安全,尤其是当你在一个团队工作的时候。

以下各项没有问题:

1
$(element).on('eventname', function () {});

但是,假设我出于任何原因需要解除绑定这个事件(想象一个禁用的按钮)。那我就得这么做了

1
$(element).off('eventname', function () {});

这将从$(element)中删除所有eventname事件。您不知道将来是否有人也会将事件绑定到该元素,并且您也会无意中取消绑定该事件。

避免这种情况的安全方法是通过

1
$(element).on('eventname.namespace', function () {});

最后,您可能注意到第一行是

1
$(element).off('eventname.namespace').on('eventname.namespace', ...)

我个人总是在绑定事件之前解除绑定,以确保不会多次调用同一事件处理程序(假设这是付款单上的提交按钮,并且该事件已绑定5次)。