Пользовательское событие в jQuery, которое не связано с элементом DOM? - PullRequest
49 голосов
/ 12 октября 2009

Мне любопытно, возможно ли создать пользовательское событие в jQuery, которое не привязано к элементу DOM.

Я очень предпочитаю jQuery YUI, но в YUI есть одна вещь, которая мне нравится: создание пользовательских событий и возможность подписки на них позже.

Например, это создает событие, которое связано с переменной, а не с элементом DOM:

var myevent = new YAHOO.util.CustomEvent("mycustomevent");

Все примеры и документация, которые я читал для jQuery, требуют что-то вроде:

$('body').bind('mycustomevent', function(){
    //do stuff
});

Ответы [ 7 ]

43 голосов
/ 12 октября 2009

Вы можете запускать пользовательские глобальные события, как это в jQuery:

jQuery.event.trigger('mycustomevent', [arg1, arg2, arg3]);

Они сработают для любого элемента.

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

Как вы написали в своем собственном ответе, вы можете привязать свое событие к глобальному объекту DOM, если не хотите связывать его с отдельным элементом страницы:

$(document).bind('mycustomevent', function (e, arg1, arg2, arg3) { /* ... */ });
39 голосов
/ 26 сентября 2014

Согласно комментарию Джона Резига , поддерживается привязка событий к пользовательским объектам через jQuery:

Нет конкретной причины, по которой он не задокументирован (кроме того, что он довольно нетрадиционен для большинства пользователей) - но да, мы поддерживаем его и проводим для него модульные тесты.

Так что это работает:

var a = {foo: 'bar'};
$(a).on('baz', function() {console.log('hello')});
$(a).triggerHandler('baz');
>>> 'hello'

Большинству пользователей потребуется triggerHandler(), а не trigger(). Если используется .trigger("eventName"), он будет искать свойство «eventName» для объекта и попытаться выполнить его после выполнения любых подключенных обработчиков jQuery ( Source ).

РЕДАКТИРОВАТЬ (28.02.2017):

После использования этого шаблона в течение 2 лет в большой кодовой базе я могу засвидетельствовать, что это плохая идея. Эти пользовательские события приводят к непонятным потокам данных. Вместо этого предпочитайте обратные вызовы.

6 голосов
/ 13 октября 2009

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

Чтобы связать пользовательское событие:

$().bind('mycustomevent', function(){
    //code here
});

Кроме того, вы можете встроить данные в объект события, который позже станет доступен:

$({mydata:'testdata'}).bind('mycustomevent',function(){
    //code here
});
4 голосов
/ 15 декабря 2010

Привязка к элементам не из dom была удалена в jQuery 1.4.4.

3 голосов
/ 28 августа 2013

jQuery Обратные вызовы предоставляют простой способ реализации системы pub-sub, независимой от DOM.

В нижней части связанной страницы приведен пример кода, который показывает, как это сделать.

3 голосов
/ 13 октября 2009

Вы по-прежнему можете произвольно запускать и отвечать на события, используя jQuery, даже если вы не знаете, к какому элементу их прикрепить. Просто создайте элемент «приемник» в вашем документе, к которому вы можете привязать все ваши пользовательские события. Это позволяет вам управлять логикой обработки событий в одном месте для всех событий, не относящихся к элементам.

$(document).ready(function() {

  $(body).append('<div id="receiver">');

  $("#receiver").bind("foo_event", function () {
    // decide what to do now that foo_event has been triggered.
  });

  $("#some_element").click(function() {
    $("#receiver").trigger("foo_event");
  });

});
1 голос
/ 02 октября 2013

[EDIT]

Вот рабочий класс, который использует концепции, изложенные ниже:

https://github.com/stratboy/image-preloader

Это просто последовательный предзагрузчик изображений. Вы можете подписаться на кучу событий. Посмотри.

[/ EDIT]

Старый пост:

Вот еще один базовый пример с обратными вызовами, подобными предложенным Химаншу П.

Я создаю класс и пришел из Mootools, где такие вещи, как классы и пользовательские события, напрямую реализуемые в классах (не привязанные к элементам DOM), абсолютно естественны. Поэтому я попробовал что-то вроде обходного пути и поделился ниже.

  var step_slider;

  //sandbox
  ;(function($) {

//constructor
var StepSlider = function(slider_mask_selector,options) {

    //this.onStep = $.Event('step');
    this.options = null;
    this.onstep = $.Callbacks();

    this.init();
}//end constructor

StepSlider.prototype = {

    init:function(){
        this.set_events();
    },//end init

    set_events:function(){

        if(this.options){
            if(this.options.onstep){
                this.subscribe('step',options.onstep);
            }
        }

    },//set_events

    subscribe:function(event,action){
        this['on'+event].add(action);
    },

    fire_onstep:function(){
        this.onstep.fire({ data1:'ok' });
    }

}//end prototype/class

//--------------------

$(document).ready(function() {

    step_slider = new StepSlider('selector');

    //for example, say that you have a div#next-button, you can then do this:
    $('#next-button').click(function(){
        step_slider.fire_onstep();
    });

});//end domready


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