JQuery 中的自定义事件?

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

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

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

153423 次浏览

我认为可以. . 可以“绑定”自定义事件,比如(from: http://docs.jquery.com/Events/bind#typedatafn) :

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

看看这个:

(根据 http://web.archive.org/web/20130120010146/http://jamiethompson.co.uk/web/2008/06/17/publish-subscribe-with-jquery/的存档版本,从过期的博客页面 http://jamiethompson.co.uk/web/2008/06/17/publish-subscribe-with-jquery/转载)


使用 jQuery 发布/订阅

2008年6月17日

为了编写一个与 Google Gears 的离线功能集成的 jQuery UI,我一直在尝试使用 jQuery 编写一些代码来轮询网络连接状态。

网络检测对象

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

$.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 的触发器和绑定方法实现发布/订阅系统的方法,这种方法在很大程度上还没有被讨论过。

演示代码比实际需要的更加迟钝。网络检测对象向文档发布“状态”事件,文档主动侦听这些事件,然后向所有订阅者发布“通知”事件(稍后详述)。这背后的原因是,在现实世界的应用程序中,可能有一些更多的逻辑控制何时以及如何发布“通知”事件。

$(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 元素仅用“订阅者”和“ networkDetect”进行分类。然后,我们可以通过触发 $(“.subscriber.networkDetection”)上的通知事件,仅将事件发布到这些元素(演示中只有一个元素)

#notifier div 是 .subscriber.networkDetection订阅者组的一部分,然后有一个绑定到它的匿名函数,有效地充当侦听器。

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

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

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

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

我想把它缩写为:

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

触发器和绑定不能说明问题的全部——这是一个 JQuery 插件。 Http://docs.jquery.com/plugins/authoring

“ enterKey”函数作为属性附加到 jQuery.fn-这是所需的代码:

(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/

上面的一个好处是,你可以在链接侦听器上优雅地处理键盘输入,比如:

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

编辑: 更新以正确地将正确的 this上下文传递给处理程序,并将任何返回值从处理程序返回给 jQuery (例如,如果您想取消事件和冒泡)。更新以向处理程序传递适当的 jQuery 事件对象,包括关键代码和取消事件的能力。

老 jsfiddle: http://jsfiddle.net/b9chris/VwEb9/24/

在接受的答案中提供的链接显示了一种使用 jQuery 实现 发布/分发系统的好方法,但是我发现代码有点难读,所以这里是我的代码的简化版本:

Http://jsfiddle.net/tfw89/5/

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

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

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

方法将事件类型和事件处理函数作为 可选地,它还可以接收与事件相关的数据作为其 第二个参数,将事件处理函数推到第三个 传递的任何数据都可用于事件 事件对象的数据属性中的处理函数 处理函数总是将事件对象作为其第一个接收 争论。

还有

方法将事件类型作为其参数 也可以接受一个值数组。这些值将传递给 事件处理函数作为事件对象后的参数。

代码如下:

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

很好的解释可以找到 给你给你。这到底为什么会有用?我发现了如何使用它在这个很好的解释从 推特工程师

在普通的 javascript 中,你可以用 新的海关事件做到这一点,但是要注意 IE 和 Safari 的问题。

下面是我如何创作自定义事件:

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

当然,你可以简单地

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

但是我编写的方式允许您检测用户是否通过执行

var prevented = event.isDefaultPrevented();

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


然后我通常会听到这样的事情

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

再说一次,你可以

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

但我总觉得这有点不安全,尤其是如果你在一个团队中工作。

以下内容没有任何问题:

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

但是,假设我需要解除这个事件的绑定,无论出于什么原因(想象一个被禁用的按钮)。我就不得不这么做

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

这将从 $(element)中删除所有 eventname事件。您无法知道将来的某个人是否也会将事件绑定到该元素,而且您也会在不经意间解除该事件的绑定

避免这种情况的安全方法是使用

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

最后,你可能已经注意到第一行是

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

私下里总是在绑定事件之前解除绑定,只是为了确保相同的事件处理程序不会被多次调用(假设这是一个支付表单上的提交按钮,而事件已经被绑定了5次)