Насколько дорог этот триггер jQuery?

#jquery #triggers

#jquery #триггеры

Вопрос:

Этот jsFiddle демонстрирует, о чем я говорю. По сути, я привязываю некоторые элементы к пользовательскому событию, а затем вызываю триггер с помощью

 $('*').trigger('myevent', args)
  

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

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

Комментарии:

1. jQuery создает список всех узлов, соответствующих селектору, затем сообщает им всем, чтобы они запустили событие. Что вы подразумеваете под » I don't know what they will be yet «?

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

3. Вы пробовали использовать Firebug для профилирования этого?

Ответ №1:

Лучшим решением является привязка и запуск событий вне документа, поскольку это будет только один элемент DOM:

 $(document).bind('myevent', function(e) {});

$(document).trigger('myevent');
  

Теперь, в конечном счете, кажется, что еще лучшим решением вашей проблемы было бы использовать делегирование событий:

 $(document).delegate('.my-delegation-selector', 'myevent', function(e) {

});
  

Взгляните на этот пример из http://api.jquery.com/delegate /

 <!DOCTYPE html>
<html>
<head>
  <style>
  p { color:red; }
  span { color:blue; }
  </style>
  <script src="http://code.jquery.com/jquery-1.5.js"></script>
</head>
<body>
  <p>Has an attached custom event.</p>
  <button>Trigger custom event</button>
  <span style="display:none;"></span>
<script>

    $("body").delegate("p", "myCustomEvent", function(e, myName, myValue){
      $(this).text("Hi there!");
      $("span").stop().css("opacity", 1)
               .text("myName = "   myName)
               .fadeIn(30).fadeOut(1000);
    });
    $("button").click(function () {
      $("p").trigger("myCustomEvent");
    });

</script>

</body>
</html>
  

Комментарии:

1. или window поскольку он не является элементом DOM и содержит всего 6 символов вместо 8 !.

2. @eli, дело в том, что я не буду знать, какие элементы будут прикреплены к триггеру. я не могу просто сказать $(#someelement, #otherelement, #etc).trigger() . мне нужно что-то общее, что просто запустит событие, и все, что связано с этим событием, сработает

3. 1 за решение его актуальной проблемы. @Jason .live злой и дорогой. .триггер дешевый.

4. @raynos .live — зло? как так?

5. @Jason ЗЛО! делегирование поиска против работы на SO.

Ответ №2:

Вы думали о pubsub? Что-то столь же простое, как.

 (function() {
    var $obj = $(window);

    window.pub = function(ev, data) {
        $obj.trigger(ev, data);
    };

    window.sub = function(ev, f) {
        $obj.bind(ev, f);
    };
})();
  

или удалите зависимость jQuery

 (function() {
    var $obj = {},
        undefined;

    window.pub = function(ev, data) {
        if ($obj[ev] === undefined) {
            return false;
        }
        for (var i = 0, len = $obj[ev].length; i < len; i  ) {
            $obj[ev][i](data);
        }
    };

    window.sub = function(ev, f) {
        if ($obj[ev] === undefined) {
            $obj[ev] = [];
        }
        $obj[ev].push(f);
    };
})();
  

Оба amplify.subscribe и Backbone.События имеют специальные объекты для этого. Возможно, вы даже найдете другие библиотеки с похожими объектами. Есть даже библиотеки PubSub.js для этого.

Пример:

 $("table.sort th").click(function(e) {
    ...
    window.pub("click.sortHeader", e); 
});

...

$.fn.pagify = function(json) {
    var table = $(this);
    ...
    //enter code here

    window.sub("click.sortHeader", function() {
         // handle table sorting.

         // adjust table pagifying plugin accordingly.
    });
};
  

В общем, pub есть trigger и sub есть bind . В этом конкретном примере у нас есть два независимых плагина. Они не знают, находятся ли они на одной странице или вообще разговаривают. Но поскольку сортировка «ломает» плагин подкачки в нашей таблице, у нас есть подписка на «событие» сортировки, чтобы исправить нашу подкачку.

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

Комментарии:

1. я никогда не слышал о pubsub … как это работает? я смотрю на это и понятия не имею, что это должно делать

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

3. @Jason небольшой пример прилагается.

4. спасибо, raynos. это идеально и именно то, что я искал. теперь я могу публиковать мои объекты всем, кто хочет подключиться к ним. потрясающе!

Ответ №3:

Смотрю на исходный код jquery. Когда вы запускаете событие в jQuery, оно проверяет наличие допустимого узла

     // don't do events on text and comment nodes
    if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
        return undefined;
    }
  

И позже проверьте наличие действительного обработчика для фактического объекта dom

     // Trigger the event, it is assumed that "handle" is a function
    var handle = jQuery._data( elem, "handle" );

    if ( handle ) {
        handle.apply( elem, data );
    }
  

Я думаю, что реальная проблема заключается в использовании селектора $ (‘*’). Попробуйте другое из предложенных решений вашей проблемы

Комментарии:

1. то есть вы хотите сказать, что это дорого делать $('*').trigger() ?

2. @Jason: Я говорю, что дорогостоящая операция связана с выбором всех узлов $ (‘*’), а не с запуском события на каждом из них, потому что не ко всем узлам прикреплен обработчик