jQuery 重复元素创建

3
以下哪个更好? 1)在每次循环中创建元素。
$(obj).children('option').each(function(){
  var item = $('<div />')
    .html($(this).text())
    .append(plus)
    .addClass('ui-widget-content ui-state-default')
    .hover(
      function(){$(this).addClass('ui-state-hover')}, 
      function(){$(this).removeClass('ui-state-hover');}
    );
    $(list).append(item);
});


2)创建元素,每次循环只更改其html
注意:这种方法不起作用,需要使用如下的.clone()方法。

var item = $('<div />')
  .addClass('ui-widget-content ui-state-default')
  .hover(
    function(){$(this).addClass('ui-state-hover')}, 
    function(){$(this).removeClass('ui-state-hover');});

$(obj).children('option').each(function(){
  $(item).html($(this).text()).append(plus);  
  $(list).append(item);
});


更新:
所以,在查看了所有答案/评论之后,这是最终的函数。 还有更多改进吗?

function create_list(obj) {
  var list = $('<div />')
    .attr('id','keyword_unselect').addClass('ui-widget')
    .delegate("div", "mouseenter mouseleave", function() {
      $(this).toggleClass('ui-state-hover');
    });

  var plus = $('<div />').addClass('ui-icon-plus');

  var item = $('<div />')
    .append(plus)
    .addClass('ui-widget-content ui-state-default');

  $(obj).children('option').each(function(){    
    item.clone(true)
      .prepend(this.text)
      .appendTo(list);
  });
  return list;
};

你改变问题中的代码有什么原因吗?这会让未来的读者感到困惑,因为现在它几乎与我的答案相同。 - user113716
如果您想要,我可以还原它,我应该还原并添加更新吗? - Hailwood
我只是想为任何决定复制和粘贴的人提供可工作的代码 ;) - Hailwood
Hailwood - 可能最好将其恢复为原始状态,以便答案有意义。未来的访问者可以参考下面答案中的代码。:o) - user113716
2个回答

1

在这种情况下,尽管第二个更好,但它目前具有不同的效果(元素每次移动)。

创建一次并使用{{link1:.clone()}}进行附加,像这样:

 var item = $('<div />', { 'class': 'ui-widget-content ui-state-default' })
                  .hover(function(){$(this).addClass('ui-state-hover')}, 
                         function(){$(this).removeClass('ui-state-hover');});

$(obj).children('option').each(function(){
  $(list).append(item.clone(true).html(this.text).append(plus));
});

你可以在这里试一试

我直接使用<option>.text属性来节省一些CPU周期,如果需要对内容进行编码,请反转此操作。


或者更高效的版本是使用 .delegate() 仅绑定一次那些 mousenetermouseleave 事件:

$(list).delegate("div", "mouseenter mouseleave", function() {
    $(this).toggleClass('ui-state-hover');
});

var item = $('<div />', { 'class': 'ui-widget-content ui-state-default' });    
$(obj).children('option').each(function(){
  $(list).append(item.clone().html(this.text).append(plus));
});

你可以在这里试一试


我注意到你正在使用toggleClass。这在这种情况下似乎没有效果? - Hailwood
@Hailwood - 当鼠标悬停(mouseneter/mouseleave)时,它将切换类的开关,因此如果它最初没有该类(因为我们在这里保证了),它将具有与您原始代码相同的效果。 - Nick Craver
你有任何想法为什么我看不到效果吗?(甚至没有错误信息) - Hailwood
@Hailwood - 在那种情况下,它会绑定处理程序两次。我稍后会仔细研究一下,现在我发布了一个更有效的版本,它不会复制这些事件处理程序,只是创建一个整个列表的一对。 - Nick Craver
@patrick - 是的,我也不确定为什么会发生这种情况,等我设置好正在工作中的Web服务器后,我会去看一下。 - Nick Craver
显示剩余4条评论

1

由于第二个版本做的事情较少,我认为可以肯定地说第二个版本会更有效率。

虽然我认为你需要使用.clone()来确保你正在使用一个新的副本。

此外,您可以将plus添加到原始文本中,然后使用.prepend()将其添加到文本中。

最后,当将其附加到list时,您可以使用.appendTo()而不是.append()

var item = $('<div />')
  .addClass('ui-widget-content ui-state-default')
  .append(plus)
  .hover(
    function(){$(this).addClass('ui-state-hover')}, 
    function(){$(this).removeClass('ui-state-hover');});

$(obj).children('option').each(function(){
  item.clone(true)
      .prepend( $.text([this]) )
      .appendTo(list);  
});

1
$.text(this) 会出问题 ;) jQuery.text 是一个 Sizzle 方法,它期望一个数组作为参数。 - Nick Craver
@Nick - 是的,我忘记了数组。谢谢你提醒我!:o) - user113716
$.text([this])$(this).text() 相比有什么不同? - Hailwood
@Hailwood - 这将会得到相同的结果,但是速度会更快,因为你不需要使用 $(this) 创建另一个 jQuery 对象。 - user113716

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接