Сравнение использования памяти браузером: встроенный onClick и использование JQuery .bind () - PullRequest
6 голосов
/ 14 марта 2011

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

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

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

|id|description|__more data_|_X__|_+__|____|____|
-------------------------------------------------
| 1|___data____|____data____|icon|icon|icon|icon|  
| 2|___data____|____data____|icon|icon|icon|icon|   
| 3|___data____|____data____|icon|icon|icon|icon|   
| 4|___data____|____data____|icon|icon|icon|icon|    

Я использую пользовательский форматер 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, как я объяснил выше
-OR, -
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 ]

8 голосов
/ 15 марта 2011

Поскольку вам нужно не только общее решение с некоторыми объектами-контейнерами, но и решение для 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 : обновленную версию кода вы можете увидеть здесь .

2 голосов
/ 14 марта 2011

Рассматривали ли вы использование 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>
2 голосов
/ 14 марта 2011

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

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

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