如何有效地处理10000 <li>?</li>

时间:2011-04-03 15:19:42

标签: javascript

在今天的采访中我被问到一个问题:

  

如何撤消<li>列表   有效?

例如,如果有列表:

<ul id="list">
    <li>1</li>
    <li>2</li>
    ...
    <li>10000</li>
</ul>

然后在反向之后,列表看起来像:

<ul id="list">
    <li>10000</li>
    ...
    <li>2</li>
    <li>1</li>
</ul>

我能提出的最有效的代码是:

function reverse(){
    var list = document.getElementById("list");
    var node_list = list.childNodes;
    var fragment = document.createDocumentFragment();
    for(var i=node_list.length-1; i>=0; i--){
       fragment.appendChild(node_list[i]);
    }
    list.appendChild(fragment);
}

但它仍然非常慢(在Chrome中需要大约10秒)。有什么想法吗?

更新:
我认为我的Chrome出了问题...我安装了Chromium并测试了上面的代码,花了不到一秒钟。

4 个答案:

答案 0 :(得分:2)

我认为面试问题的重点基本上是innerHTMLway faster而不是每个浏览器中的任何DOM操作。所以,不要使用DocumentFragment,而是使用简单的字符串:

var ul = document.getElementById("list");
var lstLi = ul.childNodes;

var str = '';

for (var i=lstLi.length - 1; i >= 0; i--) {
    str += '<li>' + lstLi[i].innerHTML + '</li>';
}
ul.innerHTML = str;

http://jsfiddle.net/bKeuD/

答案 1 :(得分:1)

DOM的工作方式,您无需重新创建区域。您需要做的就是将元素移动到已存在的ul中。最佳解决方案就是:

var ul = document.getElementById("lstLi");
var lstLi = ul.childNodes;

for (var i=0, c = lstLi.length; i < c; i++) {
    ul.insertBefore(lstLi[i], ul.firstChild);
}

基本上它的作用是它迭代每个元素并将它们放在第一位。最后,您的列表将被颠倒。

答案 2 :(得分:1)

你可以这样做:

var list = document.getElementsByTagName("ul")[0],
    items = list.childNodes,
    itemsLen = items.length;

while (itemsLen--) {
  list.appendChild(items[itemsLen]);
}

测试:http://jsbin.com/ohegu4/2/edit

如果你的问题是你不想阻止浏览器,你可以这样做:

var list = document.getElementsByTagName("ul")[0],
    items = list.childNodes,
    itemsLen = items.length;

(function reversePart() {
  var iterations = 10; // Number of processed elements every 100ms
  window.setTimeout(function(){
    while (iterations-- && itemsLen--) {
      list.appendChild(items[itemsLen]);
    }
    if (itemsLen) {
      reversePart();
    }
  }, 100); // Delay between each process : 100ms
})();

测试( 100000 li,是啊!):http://jsbin.com/ubugi3/2/edit

答案 3 :(得分:0)

Pumbaa80的基于字符串的方法是我发现反转列表的最快方法。但是,如果你真的想要使用DOM方法来反转它(例如你不想丢失列表项的属性),你可以这样做:

function reverseDom(){
  var list = document.getElementById('list');
  var items = list.childNodes;
  var length = items.length;
  var item0 = items[0];
  var i;
  list.style.display = 'none';
  for(i = 0; i < length - 1; i++)
  {
      list.insertBefore(list.lastChild, item0);
  }
  list.style.display = 'block';
}

在Linux中的Google Chrome中,上述方法花费了大约一秒来反转10,000个项目列表。但Pumbaa80的方法更快。如果您转到此链接,您可以在同一列表上并排比较这两种方法: http://jsbin.com/ubugi3/6