【问题标题】:jQuery appending an array of elementsjQuery附加一个元素数组
【发布时间】:2012-08-20 03:44:42
【问题描述】:

对于这个问题,假设我们需要 append() 1000 个对象到 body 元素。

你可以这样做:

for(x = 0; x < 1000; x++) {
    var element = $('<div>'+x+'</div>');
    $('body').append(element);
}

这可行,但对我来说似乎效率低下,因为 AFAIK 这将导致 1000 次文档重排。更好的解决方案是:

var elements = [];
for(x = 0; x < 1000; x++) {
    var element = $('<div>'+x+'</div>');
    elements.push(element);
}
$('body').append(elements);

然而,这不是一个理想的世界,这会引发错误Could not convert JavaScript argument arg 0 [nsIDOMDocumentFragment.appendChild]。我了解append() 无法处理数组。

我将如何使用jQuery(我知道DocumentFragment 节点,但假设我需要在元素上使用其他jQuery 函数,例如.css())一次向DOM 添加一堆对象以改进性能?

【问题讨论】:

  • append() 不接受字符串数组。
  • @GeorgeReith 您批准的答案比您的第一种方法还要慢。看看这个jsfiddle中的控制台日志jsfiddle.net/du2TN/2
  • @davids 很有趣,虽然我的原始代码似乎在 jQuery 1.8 中工作并且是 jQuery 方法中最快的。 (更新了你的 JSfiddle)
  • 很高兴知道 :) 无论如何,@jAndi 和 jackwander 的解决方案要快得多。但如果你更喜欢使用 jQuery,随便你吧:)
  • @davids 我需要使用 jQuery,因为它们必须是 jQuery 对象,这样我才能在其中使用其他 jQuery 函数。

标签: javascript jquery arrays performance append


【解决方案1】:

你可以打电话

$('body').append(elements.join(''));

或者你可以先创建一个大字符串。

var elements = '';
for(x = 0; x < 1000; x++) {
    elements = elements + '<div>'+x+'</div>';
}
$(document.body).append(elements);

就像你提到的,可能最“正确”的方式是使用 DocFrag。这可能看起来像

var elements = document.createDocumentFragment(),
    newDiv;
for(x = 0; x < 1000; x++) {
    newDiv = document.createElement('div');
    newDiv.textContent = x;
    elements.append( newDiv );
}
$(document.body).append(elements);

IE.textContent,需要进行条件检查才能改用.innerText.text

【讨论】:

  • @JosephSilber:当然,使用+= 没有错。我只是想在这里更加明确和表达。
  • 谢谢安迪,但我担心我过度简化了我的测试用例(我的错),我应该让每个元素都有自己的对象,这样你就可以在它们上执行像 .css() 这样的 jQuery 函数。我更新了问题中的测试用例。
  • 不应该是newDiv.textContent = x;吗?
【解决方案2】:

你可以使用一个空的 jQuery 对象而不是一个数组:

var elements = $();
for(x = 0; x < 1000; x++) {
    elements = elements.add('<div>'+x+'</div>');
    // or 
    // var element = $('<div>'+x+'</div>');
    // elements = elements.add(element);
}
$('body').append(elements);

如果您想在循环内处理新生成的元素,这可能很有用。但请注意,这将创建一个巨大的内部元素堆栈(在 jQuery 对象内)。


好像your code works perfectly fine with jQuery 1.8

【讨论】:

  • 我的实际测试解决方案有点复杂,每个元素都应该是一个独立的jquery对象,以便您可以在其上执行其他jQuery功能。我对过于简化测试用例不利。更新了问题以反映这一点。
  • 但是使用 .add 并插入最终的 jQuery 对象应该仍然可以工作。
  • 哎呀你是对的,我忘了add 不会更新原始副本。
  • @George:显然.append 的行为在 jQuery 1.8 中发生了变化。它现在也适用于 jQuery 对象数组。这是您的代码:jsfiddle.net/7Q6wm/2。我假设您使用的是旧版本。
  • 在旧版本的 jQuery 中不起作用,使用@jackwanders 描述的 document.createDocumentFragment 方法
【解决方案3】:

如果您要追求原始性能,那么我建议您使用纯 JS,尽管有些人会认为您的开发性能比您的网站/程序性能更重要。 查看 link 以获取基准测试和不同 DOM 插入技术的展示。

编辑:

出于好奇,documentFragment 被证明是最慢的方法之一。

【讨论】:

  • jsPerf 将 documentFragment 包装在 $() 调用中,这可能是它减慢速度的原因。如果您选择纯 JS 解决方案,documentFragment 仍然有用。
  • 这是一个奇怪的混合 DOM 和 jQuery 的测试,我认为它不是很有定论。
  • 它使用jQuery的each,但实际的附加是使用不同的方法完成的。
【解决方案4】:

对第二种方法稍作改动:

var elements = [],
newDiv;
for (x = 0; x < 1000; x++) {
    newDiv = $('<div/>').text(x);
    elements.push(newDiv);
}
$('body').append(elements);

$.append() 当然可以追加一个数组:http://api.jquery.com/append/

.append(内容) |内容:一个或多个附加 DOM 元素、元素数组、HTML 字符串或 jQuery 对象,插入到匹配元素集中每个元素的末尾。

【讨论】:

  • jQuery 在这方面非常严格。当它说“元素数组”时,它实际上是指 DOM 元素,而不是 jQuery 对象。事实上,使用 1.7.2,这段代码不起作用,但它在 1.8 中起作用。
【解决方案5】:

有时,jQuery 并不是最好的解决方案。如果您有很多元素要附加到 DOM,documentFragment 是一个可行的解决方案:

var fragment = document.createDocumentFragment();
for(var i = 0; i < 1000; i++) {
    fragment.appendChild(document.createElement('div'));
}
document.getElementsByTagName('body')[0].appendChild(fragment);

【讨论】:

  • 在传入数组的情况下,jQuery 不会在内部使用文档片段吗?从上面的错误看来确实如此。
  • 谢谢!这对我有用;我正在开发一个项目,该项目使用的是旧版本的 jQuery,它不处理数组,但与 createDocumentFragment 一起工作正常。
【解决方案6】:

我会使用原生 Javascript,通常要快得多:

var el = document.getElementById('the_container_id');
var aux;
for(x = 0; x < 1000; x++) {
    aux = document.createElement('div');
    aux.innerHTML = x;
    el.appendChild(aux);
}

编辑:

jsfiddle 实现了不同的选项。 @jackwander 的解决方案显然是最有效的解决方案。

【讨论】:

  • 你还在做 1000 次单独的 appendChild 操作,这会很慢。
  • @jackwanders 你是完全正确的,我已经实现了你的解决方案我的一个并且显然更快,它可以在我附加的 jsfiddle 中看到
【解决方案7】:

升级到 jQuery 1.8,按预期工作:

​$('body')​.append([
    '<b>1</b>',
    '<i>2</i>'   
])​;​

【讨论】:

    【解决方案8】:

    由于 $.fn.append 接受可变数量的元素,我们可以使用 apply 将数组作为参数传递给它:

    el.append.apply(el, myArray);
    

    如果您有一个 jQuery 对象数组,则此方法有效。根据规范,如果你有 DOM 元素,你可以附加一个元素数组。如果你有一个 html 字符串数组,你可以 .join('') 它们并一次性追加它们。

    【讨论】:

    • 谢谢。如果您坚持使用 JQuery ,这就是答案
    【解决方案9】:

    我知道,这个问题很老了,但也许它对其他人有帮助。

    或者简单的使用ECMA6扩展运算符:

    $('body').append(...elements);
    

    【讨论】:

      猜你喜欢
      • 2011-09-12
      • 2017-01-16
      • 2014-11-20
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 2012-05-24
      相关资源
      最近更新 更多