Event.observe неэффективен с прототипом JavaScript, альтернативы? - PullRequest
1 голос
/ 17 июня 2011

Итак, у нас есть таблица с множеством флажков, и вместо флажка мы хотим вызвать некоторый JavaScript мы используем что-то похожее на этот фрагмент

addEventObserver(elementId){
        // ($= means 'ends with') this is required for elementIds which are in a table and get prepended with some id
        $$('[id$=:'+elementId+']').each(function(e) {
            Event.observe(e, 'change', function(event) {
                submitAction(something);
            });
        });
}

Итак, под флажком ввода мы добавляем вызов функции javascript

<input type="checkbox" name="somename" id="somePrependedIdsomeId">    
<script type="text/javascript" language="javascript">
                    addEventObserver('someId');
                </script>

это прекрасно работает с нашими настройками тестовой среды. Хотя в производстве у нас есть таблицы с ~ 700 флажками, и это приводит к зависанию браузера / процессора.

Мы используем JSF

Ответы [ 4 ]

5 голосов
/ 17 июня 2011

Я бы отказался от добавления прослушивателя событий для каждого флажка в пользу написания одного «умного» обработчика событий, присоединенного к элементу контейнера.Вот простой пример:

var theDiv = document.getElementById("foo");
theDiv.onchange = function(e) {
    if (e.target.tagName.toLowerCase() == "input" 
          && e.target.type.toLowerCase() == "checkbox") {
        alert("do something");
    }
}

Демонстрация: http://jsfiddle.net/xFC3A/

Таким образом, событие onchange захватывается контейнером div, который имеет пузыри до.Событие, прикрепленное к div, может проверить тип элемента, который вызвал событие ( элемент source / target в зависимости от браузера ) и реагировать соответствующим образом.Основные преимущества:

  1. Только один обработчик событий - нет потери времени, связывающего обработчики с сотнями элементов.
  2. Он будет продолжать работать с динамически добавляемыми элементами (через AJAX, JS и т. Д.).

Подробнее о делегировании событий.

Некоторые полезные ссылки: http://www.quirksmode.org/js/events_properties.html

1 голос
/ 17 июня 2011

Прототип уже обеспечивает делегирование события в виде Event.on:

$('id_of_table').on('change', 'input[type=checkbox]', some_handler_function);
1 голос
/ 17 июня 2011

Я думаю, что делегирование событий должно вам помочь, просто прикрепите EventHandler к родительскому элементу всех флажков

$('container').observe("change", changeBy);

function changeBy(e){
                if (e.element().identify() != "container") {
            doChange(e.element());
        }
}

function doChange(elem){
  submitAction(something);
}

Разметка:

<div id="container"> <input type="checkbox" > ... </div>

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

1 голос
/ 17 июня 2011

Я не большой жокей из Prototype (гораздо больше из jQuery), но, вообще говоря, любой селектор, использующий селектор атрибута, будет работать медленно. Если вы используете этот селектор на 700+ предметах, вы наверняка сильно замедлитесь.

Вы также используете метод Prototype each() ... не могли бы вы переписать что-нибудь, чтобы вместо этого использовать собственный цикл javascript for ()? Опять же, ссылаясь здесь на jQuery, но я получил НЕВЕРОЯТНЫЙ прирост производительности, используя по возможности нативный JS, а не библиотечные методы. Я ускорил веб-приложение в 20 раз, удалив кучу методов jQuery .each () и заменив их родными циклами for ().

...