Как бы вы открепили все события jQuery от определенного пространства имен? - PullRequest
31 голосов
/ 07 февраля 2011

Есть ли в jQuery «глобальная» функция отмены привязки, чтобы я мог удалить все связанные события из заданного пространства имен? например:

// assume these are the events bound to different elements
$('#foo').bind('click.myNS', ...);
$('#bar').bind('keyup.myNS', ...);
$('#baz').bind('dblclick.myNS', ...);    

// magic occurs here...
$.magicalGlobalUnbindFunction('.myNS');

// ...and afterwards, the three binds from above are gone

Все примеры, которые я видел для отмены привязки, требуют, чтобы некоторые элементы были выбраны первыми. Я думаю, что технически вы могли бы сделать $('*').unbind('.myNS'), но это кажется очень неэффективным.

Ответы [ 7 ]

13 голосов
/ 07 февраля 2011

Вы можете добавить myNS как класс к каждому из элементов, для которого вы хотите отменить привязку событий.

9 голосов
/ 29 июля 2016

Вам необходимо использовать методы jQuery On и Off . Используйте документ в качестве селектора.

$(document).off('.myNS');

$(document).on('click.myNS','#foo', ...);
$(document).on('keyup.myNS','#bar', ...);
$(document).on('dblclick.myNS','#baz',''');

тогда ваши методы могут выглядеть как

$(document).on('click.myNS','#foo', fooClicked);
var fooClicked = function(e){
    var $this = $(e.target);
    // do stuff
}
9 голосов
/ 28 октября 2011

Вы всегда можете обернуть $ .fn.bind и затем кэшировать необходимые ссылки:

(function ($) {
    var origBind = $.fn.bind,
        boundHash = {};

    $.fn.bind = function (type, data, fn) {
        var namespace = '',
            events = [];

        if (typeof type === 'string') {
            // @todo check the allowed chars for event namespaces.
            namespace = type.replace(/^[^.]+/, '');

            if (namespace.length) {
                events = boundHash[namespace];

                // Namespaces can hold any number of events.
                events = boundHash[namespace] = $.isArray(events) ? events : [];

                // Only really need ref to the html element(s)    
                events.push({
                    type: type, 
                    fn: $.isFunction(fn) ? fn : data, 
                    that: this.length > 1 ? this.toArray() : this[0]
                });
            }
        }

        origBind.apply(this, arguments);
    };

    // namespace to be muffled. Feel free to qualify a specific event type.
    $.muffle = function (namespace, type) {
        var events = [];

        if (boundHash.hasOwnProperty(namespace)) {
            events = boundHash[namespace];

            $.map(events, function (event) {
                var _type = type || event.type;

                if (event.type.indexOf(_type) === 0) {
                    $(event.that).unbind(_type, event.fn);
                }
            });

            // @todo think of better return value.
            return true;
        }

        // @todo think of better return value.
        return false
    };
})(jQuery);
4 голосов
/ 26 октября 2011

Действительно, вы ищете магическую глобальную функцию, но, как всегда, с помощью магии вы можете получить только иллюзию, в данном случае, простоты.

Существует также решение jQuery, использующее .live () или .delegate () (который является единственным вариантом live ()).

Используя $("body").delegate("#foo", "click.myNs", func), вы также связываете событие, а $("#body").undelegate(".myNs") отменяете. Я использую здесь элемент «тело», но, конечно, вы можете использовать любой элемент, который является предком всех элементов, с которыми вам необходимо связать.

Это ускорит вашу работу по освобождению от обязательств, но снова заставит ваши события реагировать медленнее.

3 голосов
/ 27 октября 2011

Вам нужно взломать внутренности jQuery, вот рабочая демонстрация простой реализации:

http://jsfiddle.net/nkMQv/1/

Основная работа выполняется в обычных циклах js и не должна быть оченьнеэффективно, так как даже эта страница содержит в конечном итоге только 106 элементов для прохождения.Конечно, вы должны использовать делегирование событий как можно больше, чтобы количество элементов в коллекции обработчиков jQuery было как можно меньше.

0 голосов
/ 28 октября 2011

вы можете переопределить метод связывания jquery, а затем и в переопределении сохранить ссылку на все пространство имен и соответствующие события в ассоциативном массиве, а затем получить доступ к массиву, основываясь на событиях пространства имен, которые вы хотите отменить. Код может быть что-то вроде этого

var eventArray=[];
(function ($) {
    var bind = $.fn.bind;
    $.fn.bind= function () {
    var result = bind.apply(this, arguments);
    var selector=arguments[0];
    var nameSpace= selector.split(".")[1];   //code to select the nameSpace eg. click.myNS o/p->myNS (update this if your selector has multiple '.')
    if(!eventArray[nameSpace])    //if the associative array does not contain the namespace yet
    {
       eventArray[nameSpace]=[];
    }
    eventArray[nameSpace].push(selector);
    return result;
};
})(jQuery);

Теперь с eventArray вы можете отсоединиться, как пожелаете. Код для отмены привязки всех событий в пространстве имен myNS будет выглядеть следующим образом:

$.each(eventArray['myNS'],function(){
   $(this).unbind();
});

Надеюсь, это хорошее решение. пожалуйста, дайте мне знать, если я сделал какие-либо ошибки.

0 голосов
/ 27 октября 2011

Вы должны добавить класс в функции связывания

$('#foo').bind('click.myNS', ...).addClass('removeLater');
$('#bar').bind('keyup.myNS', ...).addClass('removeLater');
$('#baz').bind('dblclick.myNS', ...).addClass('removeLater');  

и после него

$('.removeLater').unbind();

Если #foo #bar и #etc - это все один и тот же элемент или маленькийнабор из них вы также можете сделать:

$('div, button').unbind();

, но если у вас есть связанное событие, которое вы не хотите удалять, это не будет хорошей идеей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...