【问题标题】:Browser Memory Usage Comparison: inline onClick vs. using JQuery .bind()浏览器内存使用比较:内联 onClick 与使用 JQuery .bind()
【发布时间】:2011-07-15 06:41:50
【问题描述】:

我在一个页面上有大约 400 个元素,这些元素与它们相关联的点击事件(4 种不同类型的按钮,每种有 100 个实例,每种类型的点击事件执行相同的功能但具有不同的参数)。

我需要尽量减少这可能对性能产生的任何影响。通过将单击事件单独绑定到每个事件(使用 JQuery 的bind()),我会受到什么样的性能影响(内存等)?让内联onclick 在每个按钮上调用函数会更有效吗?

编辑澄清:):
我实际上有一个表(使用 JQGrid 生成),每行都有数据列,后跟 4 个图标“按钮”列-删除和其他三个使 AJAX 回调到服务器的业务功能:

|id|描述|__更多数据_|_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. 使用custom formatter 构建图标图像(每种图标类型都有自己的类名)。
  2. afterInsertRow JQGrid 事件中将图标的data() 设置为其参数。
  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 元素 :)

【问题讨论】:

  • 事件委托是这里唯一合理的解决方案。

标签: jqgrid onclick memory-management jquery


【解决方案1】:

因为您不仅需要包含一些容器对象的通用解决方案,还需要 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 answer 准备的the demo。如果您从事件绑定方面查看“操作”格式化程序的代码,则其工作方式与您当前的代码基本相同。

UPDATED 2:更新后的代码可以看here

【讨论】:

  • @icats:我也这么认为,在写完你的问题的答案后写了the suggestion
  • 非常感谢!!!您的回答非常简洁且很有帮助。我很欣赏这些演示,非常感谢!!!正如您在对上述问题的回答中提到的那样,“操作”自定义格式类型似乎并不完全完整/有据可查:“格式化程序只是实验性的,将在下一个版本中进行描述”。我期待下一个 JQGrid 版本!因此,我将使用您上面概述的“beforeSelectRow”事件处理程序方法。这是完美的,非常简单!我想我在盒子里想太多了:)。
  • 另外,您对 JQGrid 团队的建议是完美的。那会很方便!
【解决方案2】:

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

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

【讨论】:

  • +1 但是其中最密集的部分是生成所有这些按钮并将其插入到 DOM 中,他不应该在按钮插入到 DOM 之前将点击处理程序绑定到按钮吗?
  • @motionman,我假设这些元素是在服务器端创建的,而不是使用 javascript 即时创建的。关于绑定处理程序,no。委托的全部意义在于不必绑定到每个元素,而是由于冒泡而获得事件的那些元素的父级。因此,单个绑定将处理所有点击(即使它们是在绑定之后添加的,因为绑定发生在另一个元素上)。
  • @motionman - 我在上面澄清了我的问题,非常感谢您的意见!我确实使用 Javascript 即时创建元素。
  • @icats 你应该看看@oleg 答案。
【解决方案3】:

您是否考虑过使用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>

【讨论】:

  • 非常感谢@KenRedler! delegate()data()- 不知道这些我觉得很傻。我在上面的问题中添加了说明-delegete() 看起来如果我设置正确,它将对我有用,但我不太确定实现我需要做的最有效的方法。
猜你喜欢
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-31
  • 1970-01-01
相关资源
最近更新 更多