Сравнение использования памяти браузером: встроенный 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()
(как указано в ответах ниже (большое спасибо!))
- Создайте изображение значка (каждый тип значка имеет свое собственное имя класса) с помощью пользовательского средства форматирования.
- Установить значок
data()
к его параметрам в событии afterInsertRow JQGrid. - Применить
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()
метод.