Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

JavaScript快速加载超大列表

  其实JavaScript的运行效率并不慢,感觉它慢是因为被DOM和CSS渲染拖累的。当有巨大的DOM树需要操作的时候,如果全让DOM自己来做肯定卡的要死。不信的话可以加载个一百万元素的列表试试,要是机器比较差直接把浏览器都跑崩溃了,更别提在上面操作。所以我们需要把大数据留在内存中,只把需要的部分给DOM呈现。之前的文章(列表即时搜索效果)中也有稍微的实现了一下,但是那篇文章主要说的是搜索功能,对于呈现方面也只是做到了“能显示”的程度。而且那时候用的列表比较小,没有什么感觉。现在我们来显示一个100万个项的列表试试。下面是代码 <!DOCTYPE html>
<style>
#list {
  position:relative;
  border:1px solid #CCC;
  width:100px;height:500px;
  overflow:auto;
}
#list li {
  position:absolute;left:0px;
  height:20px;overflow:hidden;
  font:12px/20px Consolas;
}
</style>
<script>
window.onload=function(){
  //声明、初始化一些变量
  var i,s=[],list,last;
  list=document.getElementById("list");
  //列表滚动事件
  list.onscroll=function(){
    var n,l,r,i,o;
    //计算当前应该显示的第一个元素的下标
    n=list.scrollTop/20|0;
    //前后添加20个作为缓冲
    l=n-20;r=n+45;
    if(l<0)l=0;
    if(r>=s.length)r=s.length;
    //遍历已经显示的,如果它此时不需要显示就把它从UL中移除
    //其实这个操作不是必要的,但是添加可个操作可是使得列表更容易扩展
    i=0;
    while(o=list.children[i])
      if(o.ind>=l&&o.ind<r||o==last)i++;
      else list.removeChild(o);
    //最后是显示该显示的项
    while(l<r)show(l++);
  };
  //生成100万个数据,这个通常是直接从服务器加载的
  //所以测试程序性能时,它消耗的效率不该算入
  for(i=0;i<1E6;i++)s.push({n:"item"+i});
  //显示这个数据数组的最后一项
  show(s.length-1);
  //保存这最后一项的DOM,因为为了保持滚动条,它必须始终显示
  last=list.lastChild;
  //主动调用scroll,加载初始显示的项
  list.onscroll();
  //show函数的声明,参数是数组下标
  function show(i){
    //获取改项对应的DOM对象
    var o=s[i].node;
    if(!o){//判断是否存在,不存在就创建
      s[i].node=o=document.createElement("li");
      o.appendChild(document.createTextNode(s[i].n));
      o.ind=i;//直接在DOM对象上保存数组下标
    };
    //判断是否是UL的子节点,如果不是就放入UL中
    //这里可以优化,不过这个测试程序这样就足够了
    if(!list.contains(o))list.appendChild(o);
    //最后调整需要显示的位置
    //如果是100万的话,有些浏览器的CSS可能支持不了,因为超出CSS的坐标上限了
    o.style.top=20*i+"px";
  };
};
</script>
<ul id="list"></ul>
  这样的程序就比之前的好很多,如果排除掉加载数据使用的时间,这个程序就几乎是瞬间显示的。但是和之前的程序一样,快速拖动滚动条会让列表暂时变的空白。这貌似没什么解决的办法了,微软的Windows中也存在这个问题。这个测试数据是100万,有些浏览器的CSS对坐标的支持上限可没那么多,这个问题可以分列表解决,不过好麻烦也懒的做。通常10万数据同时加载的情况就已经不得了了,100万只是作为逻辑上的测试数据而已。所以不用纠结这么多啦。
网名:
3.80.32.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^