附加jQuery事件处理程序,以便首先触发它们

Jac*_*cob 35 jquery events binding

有没有办法附加一个jQuery事件处理程序,以便在任何以前附加的事件处理程序之前触发处理程序?我遇到过这篇文章,但是代码没有用,因为事件处理程序不再存储在数组中,这正是他的代码所期望的.我试图创建一个jQuery扩展来做我想要的,但这不起作用(事件仍按照它们绑定的顺序触发):

$.fn.extend({
    bindFirst: function(type, handler) {

        var baseType = type;
        var dotIdx = type.indexOf('.');
        if (dotIdx >= 0) {
            baseType = type.substr(0, dotIdx);
        }

        this.each(function() {
            var oldEvts = {};
            var data = $.data(this);
            var events = data.events || data.__events__;
            var handlers = events[baseType];
            for (var h in handlers) {
                if (handlers.hasOwnProperty(h)) {
                    oldEvts[h] = handlers[h];
                    delete handlers[h];
                    // Also tried an unbind here, to no avail
                }
            }

            var self = $(this);
            self.bind(type, handler);

            for (var h in oldEvts) {
                if (oldEvts.hasOwnProperty(h)) {
                    self.bind(baseType, oldEvts[h]);
                }
            }
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

是否有一种自然的方式来重新排序事件处理?如果没有,你知道我可以申请的技术吗?我正在使用jQuery 1.4.1,但如果必须我会升级.

use*_*716 14

这是我做了一段时间的简单插件.允许您将处理程序绑定到列表的开头.它非常简单,我不保证它适用于命名空间事件或任何非常奇特的事情.

对于简单地绑定单个或空间单独的事件组,它应该工作.

示例: http ://jsfiddle.net/gbcUy/

$.fn.bindUp = function(type, fn) {

    type = type.split(/\s+/);

    this.each(function() {
        var len = type.length;
        while( len-- ) {
            $(this).bind(type[len], fn);

            var evt = $.data(this, 'events')[type[len]];
            evt.splice(0, 0, evt.pop());
        }
    });
};
Run Code Online (Sandbox Code Playgroud)

或者,如果您想以其他方式操作处理程序数组,只需获取所需元素的处理程序,然后根据需要对其进行操作:

示例: http ://jsfiddle.net/gbcUy/1/

var clickHandlers = $('img').data('events').click;

clickHandlers.reverse(); // reverse the order of the Array
Run Code Online (Sandbox Code Playgroud)

  • @PetrPeller jQuery 1.7中内部事件注册逻辑已更改; 你需要在以后的版本中使用`$ ._ data($ el [0]).events`. (5认同)

Jor*_*ray 8

有一种称为相当不错的插件jQuery.bind-第一,它提供的天然类似物on,bind,delegatelive方法这推动将事件注册队列的顶部.它还考虑了1.7和早期版本之间事件注册的差异.以下是如何使用它:

$('button')
    .on     ('click', function() { /* Runs second */ })
    .onFirst('click', function() { /* Runs first  */ });
Run Code Online (Sandbox Code Playgroud)

与大多数这些答案一样,最大的缺点是它依赖于jQuery的内部事件注册逻辑,并且如果它发生变化就很容易破坏 - 就像在1.7版本中那样!对于项目的寿命来说,找到一个不涉及劫持jQuery内部的解决方案可能会更好.

在我的特殊情况下,我试图让两个插件玩得很好.我使用自定义事件处理它,如方法文档中所述trigger.您可以根据自己的情况采用类似的方法.这是一个让你入门的例子:

$('button')
    .on('click', function() {
        // Declare and trigger a "before-click" event.
        $(this).trigger('before-click');

        // Subsequent code run after the "before-click" events.
    })
    .on('before-click', function() {
        // Run before the main body of the click event.
    });
Run Code Online (Sandbox Code Playgroud)

并且,如果需要,这里是如何设置传递给处理函数的事件对象的属性并访问before-click要执行的最后一个事件的结果:

// Add the click event's pageX and pageY to the before-click event properties.
var beforeClickEvent = $.Event('before-click', { pageX: e.pageX, pageY: e.pageY });
$(this).trigger(beforeClickEvent);

// beforeClickEvent.result holds the return value of the last before-click event.
if (beforeClickEvent.result === 'no-click') return;
Run Code Online (Sandbox Code Playgroud)