Сравнение использования памяти браузером: встроенный onClick и использование JQuery .bind()

У меня ~400 элементов на странице, к которым привязаны события кликов (4 разных типа кнопок с 100 экземплярами каждого, каждый клик для каждого типа выполняет одну и ту же функцию, но с разными параметрами).

Мне нужно минимизировать любое влияние на производительность, которое это может иметь. Какую производительность я беру (память и т. Д.), Привязывая события клика к каждому из них по отдельности (используя JQuery bind())? Будет ли эффективнее иметь встроенный onclick вместо этого вызывать функцию для каждой кнопки?

Изменить для уточнения:):
На самом деле у меня есть таблица (сгенерированная с использованием JQGrid), и в каждой строке есть столбцы данных, за которыми следуют 4 столбца со значком "кнопка" - удаление и три другие бизнес-функции, которые вызывают вызовы AJAX на сервер:

| id | описание |__more data_|_X__|_+__|____|____|
-------------------------------------------------
| 1|___ данные ____ | ____ данные ____ | значок | значок | значок | значок |  
| 2|___ данные ____ | ____ данные ____ | значок | значок | значок | значок |   
| 3|___ данные ____ | ____ данные ____ | значок | значок | значок | значок |   
| 4|___ данные ____ | ____ данные ____ | значок | значок | значок | значок |    

Я использую пользовательский форматировщик JQGrid ( http://www.trirand.com/jqgridwsiki/doku.php?id=wiki:custom_formatter), чтобы создать значок "кнопки" в каждой строке (я не могу получить кнопку HTML с сервера).

Именно здесь, в моей пользовательской функции форматирования, я могу легко встроить иконку HTML и код в строку onclick вызов соответствующих функций с соответствующими параметрами (данные из других столбцов в этой строке). Я использую данные в столбцах строк в качестве параметров для своих функций.

    function removeFormatter(cellvalue, options, rowObject) {       
        return "<img src='img/favoritesAdd.gif' onclick='remove(\"" + options.rowId + "\")' title='Remove' style='cursor:pointer' />";
    }

Итак, я могу придумать два варианта:
1) встроенный onclick как я объяснил выше
--или же--
2) delegate() (как указано в ответах ниже (большое спасибо!))

  1. Создайте изображение значка (каждый тип значка имеет свое собственное имя класса) с помощью пользовательского средства форматирования.
  2. Установить значок data() к его параметрам в событии afterInsertRow JQGrid.
  3. Применить delegate() обработчик кнопок определенных классов (как сказано ниже @KenRedler)
>    $('#container').delegate('.your_buttons','click',function(e){  
>      e.preventDefault();  
>      var your_param = $(this).data('something'); // store your params in data, perhaps  
>      do_something_with( your_param );  
>    }); //(code snippet via @KenRedler)

Я не уверен, насколько браузерная опция № 2, я думаю... но мне нравится держать Javascript подальше от моих элементов DOM:)

3 ответа

Решение

Поскольку вам нужно не только общее решение с некоторыми объектами-контейнерами, но и решение для jqGrid, я могу предложить вам еще один способ.

Проблема в том, что jqGrid делает уже несколько onClick привязок. Таким образом, вы не будете тратить больше ресурсов, если просто используете существующий в обработчике событий jqGrid. Вам могут пригодиться два обработчика событий: onCellSelect и beforeSelectRow. Чтобы поведение было в основном близко к тому, что у вас есть в настоящее время, я предлагаю вам использовать событие beforeSelectRow. Преимущество состоит в том, что если пользователь нажмет одну из ваших пользовательских кнопок, выбор строки может остаться без изменений. С помощью onCellSelect сначала будет выбрана строка, а затем вызван обработчик события onCellSelect.

Вы можете определить столбцы с помощью кнопок, как показано ниже

{ name: 'add', width: 18, sortable: false, search: false,
  formatter:function(){
      return "<span class='ui-icon ui-icon-plus'></span>"
  }}

В приведенном выше коде я использую пользовательский форматер jqGrid, но без привязки к событию. Код

beforeSelectRow: function (rowid, e) {
    var iCol = $.jgrid.getCellIndex(e.target);
    if (iCol >= firstButtonColumnIndex) {
        alert("rowid="+rowid+"\nButton name: "+buttonNames[iCol]);
    }

    // prevent row selection if one click on the button
    return (iCol >= firstButtonColumnIndex)? false: true;
}

где firstButtonColumnIndex = 8 а также buttonNames = {8:'Add',9:'Edit',10:'Remove',11:'Details'}, В вашем коде вы можете заменить alert на соответствующий вызов функции.

Если вы хотите выбрать строку всегда при нажатии кнопки, вы можете упростить код до следующего

onCellSelect: function (rowid,iCol/*,cellcontent,e*/) {
    if (iCol >= firstButtonColumnIndex) {
        alert("rowid="+rowid+"\nButton name: "+buttonNames[iCol]);
    }
}

Как вы используете один из существующих click обработчик событий привязан ко всей таблице (см. исходный код) и просто скажите jqGrid, какой дескриптор вы хотите использовать.

Я рекомендую вам дополнительно всегда использовать gridview:true которые ускоряют сборку jqGrid, но которые нельзя использовать, если вы используете afterInsertRow функция, которую вы решили использовать в качестве опции.

Вы можете увидеть демо здесь.

ОБНОВЛЕНО: еще один вариант, который у вас есть, это использовать formatter:'actions' посмотрите демо, подготовленное к ответу. Если вы посмотрите на код форматера 'actions', он работает в основном как ваш текущий код, если вы посмотрите на него со стороны привязки событий.

ОБНОВЛЕНО 2: Обновленную версию кода вы можете увидеть здесь.

Рассматривали ли вы использование delegate()? У вас будет один обработчик элемента контейнера, а не сотни. Что-то вроде этого:

$('#container').delegate('.your_buttons','click',function(e){
  e.preventDefault();
  var your_param = $(this).data('something'); // store your params in data, perhaps
  do_something_with( your_param );
});

Предполагая общий макет, как это:

<div id="container">
  <!--- stuff here --->
  <a class="your_buttons" href="#" data-something="foo">Alpha</a>
  <a class="your_buttons" href="#" data-something="bar">Beta</a>
  <a class="your_buttons" href="#" data-something="baz">Gamma</a>
  <a class="something-else" href="#" data-something="baz">Omega</a>
  <!--- hundreds more --->
</div>

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

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

Другие вопросы по тегам