浏览器内存使用情况比较:内联onClick与使用JQuery .bind()

时间:2011-03-14 19:32:23

标签: jqgrid onclick memory-management jquery

我在页面上有大约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)。

在我的自定义格式化程序功能中,我可以轻松地在内联onclick中构建图标HTML和代码,并使用适当的参数调用相应的函数(来自该行中其他列的数据)。我使用行列中的数据作为我的函数的参数。

    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. 使用custom formatter构建图标图像(每种图标类型都有自己的类名称。)
  2. 将图标的data()设置为delegate()中的参数3}} JQGrid事件。
  3. > $('#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) 处理程序应用于特定类的按钮(如下所述@KenRedler)
{{1}}

我不确定浏览器密集型选项#2是多少...我想确保Javascript远离我的DOM元素:)

3 个答案:

答案 0 :(得分:8)

因为你不仅需要一些带有一些容器对象的通用解决方案,而且还有jqGrid的解决方案,我可以再提示一下。

问题是jqGrid已经创建了一些onClick绑定。因此,如果您只使用jqGrid事件处理程序中的现有资源,则不会花费更多资源。两个事件处理程序对您有用:onCellSelectbeforeSelectRow。为了与您目前拥有的内容大致相近,我建议您使用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 = 8buttonNames = {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事件处理程序的方式(请参阅the source code),然后说jqGrid您想要使用的句柄。

我建议你另外总是使用gridview:true来加速jqGrid的构建,但如果你使用afterInsertRow函数作为一个选项,那就不能使用它。

您可以看到演示here

更新:您还有一个选项是formatter:'actions'使用为the demo准备的the answer。如果你看一下'actions'的代码,那么格式化程序的工作方式就像你当前的代码一样,如果你从事件绑定方面看它。

更新2 :您可以看到的here代码的更新版本。

答案 1 :(得分:2)

您应该使用.delegate()方法通过jQuery将所有元素的单击处理程序绑定到所有按钮的父元素。

对于不同的参数,您可以对每个元素使用data-属性,并使用.data()方法检索它们。

答案 2 :(得分: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>