jQuery事件处理程序总是按绑定的顺序执行-可以解决这个问题吗? [英] jQuery event handlers always execute in order they were bound - any way around this?

查看:78
本文介绍了jQuery事件处理程序总是按绑定的顺序执行-可以解决这个问题吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

令人讨厌的是jQuery事件处理程序总是按照绑定的顺序执行.例如:

It can be anoying that jQuery event handlers always execute in the order they were bound. For example:

$('span').click(doStuff1);
$('span').click(doStuff2);

单击跨度将导致触发doStuff1(),然后触发doStuff2().

clicking on the span will cause doStuff1() to fire, followed by doStuff2().

当我绑定doStuff2()时,我希望可以选择 之前 doStuff1()进行绑定,但是似乎没有任何简便的方法为此.

At the time I bind doStuff2(), I would like the option to bind it before doStuff1(), but there doesn't appear to be any easy way to do this.

我想大多数人会说,只需编写如下代码:

I suppose most people would say, just write the code like this:

$('span').click(function (){
    doStuff2();
    doStuff1();
});

但这只是一个简单的例子-实际上,这样做并不总是很方便.

But this is just a simple example - in practise it is not always convienient to do that.

在某些情况下,您想绑定事件,并且要绑定的对象已经具有事件.在这种情况下,您可能只是希望新事件在其他任何现有事件之前触发.

There are situations when you want to bind an event, and the object you are binding to already has events. And in this case you may simply want the new event to fire before any other existing events.

那么在jQuery中实现这一目标的最佳方法是什么?

So what is the best way to achieve this in jQuery?

推荐答案

更新后的答案

jQuery更改了事件在1.8中的存储位置.现在,您知道为什么搞乱内部API真是个坏主意:)

jQuery changed the location of where events are stored in 1.8. Now you know why it is such a bad idea to mess around with internal APIs :)

用于访问DOM对象事件的新 内部 API可通过全局jQuery对象获得,并且不与每个实例绑定,并且使用DOM元素作为第一个参数,而键(对我们来说是事件")作为第二个参数.

The new internal API to access to events for a DOM object is available through the global jQuery object, and not tied to each instance, and it takes a DOM element as the first parameter, and a key ("events" for us) as the second parameter.

jQuery._data(<DOM element>, "events");

这是jQuery 1.8的修改代码.

So here's the modified code for jQuery 1.8.

// [name] is the name of the event "click", "mouseover", .. 
// same as you'd pass it to bind()
// [fn] is the handler function
$.fn.bindFirst = function(name, fn) {
    // bind as you normally would
    // don't want to miss out on any jQuery magic
    this.on(name, fn);

    // Thanks to a comment by @Martin, adding support for
    // namespaced events too.
    this.each(function() {
        var handlers = $._data(this, 'events')[name.split('.')[0]];
        // take out the handler we just inserted from the end
        var handler = handlers.pop();
        // move it at the beginning
        handlers.splice(0, 0, handler);
    });
};

这是一个游乐场.

原始答案

正如@Sean发现的那样,jQuery通过元素的data接口公开了所有事件处理程序.特别是element.data('events').使用此功能,您始终可以编写一个简单的插件,从而可以在特定位置插入任何事件处理程序.

As @Sean has discovered, jQuery exposes all event handlers through an element's data interface. Specifically element.data('events'). Using this you could always write a simple plugin whereby you could insert any event handler at a specific position.

这是一个简单的插件,它的作用是在列表的开头插入一个处理程序.您可以轻松地扩展它以在任何给定位置插入项目.这只是数组操作.但是,由于我还没有看到jQuery的源代码,也不想错过任何发生的jQuery魔术,所以通常我通常先使用bind添加处理程序,然后重新组合数组.

Here's a simple plugin that does just that to insert a handler at the beginning of the list. You can easily extend this to insert an item at any given position. It's just array manipulation. But since I haven't seen jQuery's source and don't want to miss out on any jQuery magic from happening, I normally add the handler using bind first, and then reshuffle the array.

// [name] is the name of the event "click", "mouseover", .. 
// same as you'd pass it to bind()
// [fn] is the handler function
$.fn.bindFirst = function(name, fn) {
    // bind as you normally would
    // don't want to miss out on any jQuery magic
    this.bind(name, fn);

    // Thanks to a comment by @Martin, adding support for
    // namespaced events too.
    var handlers = this.data('events')[name.split('.')[0]];
    // take out the handler we just inserted from the end
    var handler = handlers.pop();
    // move it at the beginning
    handlers.splice(0, 0, handler);
};

例如,对于此标记,它的工作方式如下(此处的示例):

So for example, for this markup it would work as (example here):

<div id="me">..</div>

$("#me").click(function() { alert("1"); });
$("#me").click(function() { alert("2"); });    
$("#me").bindFirst('click', function() { alert("3"); });

$("#me").click(); // alerts - 3, then 1, then 2

但是 ,据我所知,由于.data('events')并不是其公共API的一部分,如果附加的基本表示形式,对jQuery的更新可能会破坏您的代码例如,事件从数组更改为其他内容.

However, since .data('events') is not part of their public API as far as I know, an update to jQuery could break your code if the underlying representation of attached events changes from an array to something else, for example.

免责声明:由于一切皆有可能:),这是您的解决方案,但是我仍然会在重构现有代码方面犯错,因为只是想记住这些项目的附加顺序很快就会消失随着您不断添加越来越多的这些有序事件.

这篇关于jQuery事件处理程序总是按绑定的顺序执行-可以解决这个问题吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆