zoukankan      html  css  js  c++  java
  • js DOM优化相关探索

    我在这尝试两个方面:-->DOM与js

                                -->DOM与浏览器

    (最近在秒味视频上学到不少,哈哈哈)

    一、DOM与js

          1.js与dom的交互问题

          频繁的与dom交互,是一件浪费时间与金钱的事情,这就需要我们尽量改进自己的代码,让我们想做的事情尽量在js中做的差不多了在去跟dom打交道。 

          下面的小例子就说明了问题:

     1 <!DOCTYPE html>
     2 <html lang="zh">
     3 <head>
     4 <meta charset=utf-8>
     5 <title>dom优化相关</title>
     6 </head>  
     7 <style>  
     8    
     9 </style>  
    10     
    11 <body>
    12     <div id="div1"></div>
    13      <script>
    14         window.onload =  function(){
    15             var nDiv = document.getElementById('div1');
    16             var str = '';
    17 
    18             /*console.time("innerHTML10000个a所用的时间");
    19             //每次循环dom都与js交互,太浪费时间啦
    20             for(var i=0;i<10000;i++){
    21                 nDiv.innerHTML += 'a';
    22             }
    23             console.timeEnd("innerHTML10000个a所用的时间");*/
    24 
    25             console.time("获得10000个a之后innerHTML所用的时间");
    26             //这种就减少了js与dom的交互,大量的循环只在js中实现
    27             for(var i=0;i<10000;i++){
    28                 str += 'a';
    29             }
    30             nDiv.innerHTML = str;
    31             console.timeEnd("获得10000个a之后innerHTML所用的时间");
    32 
    33         }
    34     </script>
    35 </body>  
    36 </html>

    (在chrome下)

    这个时间的对比还是比较明显的喔。 对了,这console.time()和console.timeEnd()还挺好用的吧,其实console 还有好多亮瞎人眼的方法,可以自行google或百度脑补。

    <------STOP  START------->:

       写到上面代码时,用到了window.onload,然后这里暂时说点别的,看下面的代码:

        

    1        function t(){
    2             alert("1")
    3             }
    4         function b(){
    5             alert("2")
    6             }
    7          window.onload =t ;
    8          window.onload =b ;

     对吧,这只会alert('2')嘛,也就是说window.onload不能同时加载多个函数,后面的会覆盖掉前面的。

     那怎么办呢? 这有一个简单易用的方法:

     1  function t(){
     2             alert("1")
     3             }
     4   function b(){
     5             alert("2")
     6             }
     7    window.onload = function(){
     8             t();
     9             b();
    10          }

    这样就可以1和2都弹窗了。

    不过更加庆幸的是,我们还有更好的方法来为 一个事件指派多个处理程序了那就是addEventListener和attachEvent:

     1        if(window.attachEvent){
     2             window.attachEvent('onload',function(){
     3                 alert('ie1');               
     4             });
     5             window.attachEvent('onload',function(){
     6                 alert('ie2');               
     7             });
     8         }else{
     9             window.addEventListener('load',function(){
    10                 alert('1');
    11             });
    12             window.addEventListener('load',function(){
    13                 alert('2');
    14             });
    15         }

    就是ie中可能执行顺序会有点不一样而已啦。

    <------STOP  END------->

       2.在于dom交互时innerHTML与dom方法(像appendChild()这样的方法)之间的效率比较:

     1 <!DOCTYPE html>
     2 <html lang="zh">
     3 <head>
     4 <meta charset=utf-8>
     5 <title>dom优化相关</title>
     6 </head>  
     7 <style>  
     8    
     9 </style>  
    10     
    11 <body>
    12     <div id="div1"></div>
    13     <ul id="oul"></ul>
    14     <script>
    15 
    16         window.onload =  function(){
    17             var UL = document.getElementById('oul');
    18             var str='';
    19             
    20             
    21             console.time('dom操作所用时间');
    22             for(var i=0;i<10000;i++){
    23                 var LI = document.createElement('li');
    24                 UL.appendChild(LI);
    25             }
    26             console.timeEnd('dom操作所用时间');
    27 
    28             console.time('innerHTML操作所用时间');
    29             for(var i=0;i<10000;i++){
    30                 str += '<li></li>';
    31             }
    32             UL.innerHTML = str;
    33             console.timeEnd('innerHTML操作所用时间');        
    34         }
    35 
    36 
    37  
    38     </script>
    39 </body>  
    40 </html>

    下面是时间对比:

    chrome:

    FF:

    奇异的事实证明两个浏览器下都是dom方法运行速度比较快。在我以前的认知里面两个浏览器的表现不应该是一致的,感觉ff下innerHTML应该会比dom快的。

    此处也求高人指点。

     3.我们知道与dom相关的行为都会牵扯到时间问题,那么怎么减少dom操作呢?

        ---->使用节点克隆

      

     1 <!DOCTYPE html>
     2 <html lang="zh">
     3 <head>
     4 <meta charset=utf-8>
     5 <title>dom优化相关</title>
     6 </head>  
     7 <style>  
     8    
     9 </style>  
    10     
    11 <body>
    12     <div id="div1"></div>
    13     <ul id="oul"></ul>
    14     <script>
    15        window.onload =  function(){
    16             var UL = document.getElementById('oul');
    17             var str='';
    18             
    19            
    20             /*console.time('dom操作所用时间');
    21             for(var i=0;i<10000;i++){
    22                 var LI = document.createElement('li');
    23                 LI.innerHTML = 'li';
    24                 UL.appendChild(LI);
    25             }
    26             console.timeEnd('dom操作所用时间');*/
    27 
    28             
    29             console.time('克隆节点所用时间');
    30             var LI = document.createElement('li');
    31             LI.innerHTML = 'li'; 
    32             for(var i=0;i<10000;i++){
    33                 var newLi = LI.cloneNode(true);
    34                 UL.appendChild(LI);
    35             }
    36             console.timeEnd('克隆节点所用时间');
    37 
    38                    
    39         }
    40 
    41 
    42        
    43     </script>
    44 </body>  
    45 </html>

    虽然相差不大,但是还是不一样的:

    chrome:

      --->尽量使用局部变量

           下面两种写法也是会影响效率的,因为每次都要获取aLi.length集合也是要代价的,保存成局部变量会好些那。

              for(var i=0;i<aLi.length;i++){
                    aLi[i].innerHTML = 'li';
                }
                var  len = aLi.length;
                for(var i=0;i<len;i++){
                    aLi[i].innerHTML = 'li';
                }

    在上面添加10000个节点例子中尝试:

        同样的下面两种写法也是有区别的:

      

                var Div = document.getElementById();
                var LI = document.getElementById();
                var Input = document.getElementById();
                //改成下面这样会比较好
                var doc = document;
                var Div = doc.getElementById();
                var LI = doc.getElementById();
                var Input = doc.getElementById();

     ---->还有就是尽量只是用获取元素节点的方法:

       

                childNodes -->元素节点、文本节点
                children--> 元素节点
                 (利用querySelectorAll)
                var oul  = document.getElementById('uli');
                var ali = oul.getElementById('li');
                -->
                var aLi = document.querySelectorAll('#uli li');

    二、dom与浏览器

        1.添加操作(尽量在appendChild前添加操作)

     1 <!DOCTYPE html>
     2 <html lang="zh">
     3 <head>
     4 <meta charset=utf-8>
     5 <title>dom优化相关</title>
     6 </head>  
     7 <style>  
     8    #div1 {
     9      width: 100px;
    10      height: 100px;
    11      background: red;
    12      position: absolute;
    13    }
    14 </style>  
    15     
    16 <body>
    17     <div id="div1"></div>
    18     <ul id="oul"></ul>
    19     <script>
    20          window.onload = function(){
    21             var oul = document.getElementById('oul');
    22           
    23             console.time('dom操作时间');
    24             for(var i=0;i<10000;i++){
    25                 var oli = document.createElement('li');
    26                 //注意下面两句的位置
    27                 //oul.appendChild(oli);
    28                 //oli.innerHTML = 'li';
    29                 oli.innerHTML = 'li';
    30                 oul.appendChild(oli);
    31                 
    32               }
    33             }
    34             console.timeEnd('dom操作时间');
    35          }
    36 
    37     </script>
    38 </body>  
    39 </html>

    还是有一定的差别喔,可以自己动手试一下。

       2.合并dom操作(利用cssText)

     window.onload = function(){
                var oul = document.getElementById('oul');
              
                console.time('dom操作时间');
                for(var i=0;i<10000;i++){
                    var oli = document.createElement('li');
                    //事实上我们总以为下面第二种方法会更好些,时间会更短,但是,分别在FF和chrome中测试的话,还是有点奇妙的。(chrome中神奇的第二种更快些)
                    oli.style.width = '100px';
                    oli.style.height = '100px';
                    oli.style.background = 'red';
                    //oli.style.cssText = '100px;height:100px;background:red';
                }
                console.timeEnd('dom操作时间');
            }

      3.缓存布局信息:

    window.onload = function(){
                var oDiv = document.getElementById('div1');
                var l = oDiv.offsetLeft;
                var t = oDiv.offsetTop;
    
                //setInterval(function(){
                //    oDiv.style.left = oDiv.offsetLeft + 1 + 'px';
                //    oDiv.style.top = oDiv.offsetTop + 1 + 'px';
                //},30);
                //把总是会用到的布局信息缓存起来,这样就不用总是频繁的去访问dom了
                setInterval(function(){
                    l++;
                    t++;
                    oDiv.style.left = l + 1 + 'px';
                    oDiv.style.top = t + 1 + 'px';
                },30);
            }

     我这里一般测试时间都是在chrome下,有的ff或别的浏览器不一定会一样喔,欢迎留言一起钻研。

  • 相关阅读:
    Git 一些关于 Git、Github 的学习资源
    迁移应用数据库到MySQL Database on Azure
    释放虚拟磁盘未使用空间来减少计费容量
    链路层的双链路--大型服务器的优化体系
    解读 Windows Azure 存储服务的账单 – 带宽、事务数量,以及容量
    产品技术恩仇记:这个需求真的很简单吗?
    语音识别真的比肩人类了?听听阿里iDST初敏怎么说
    《伟大的计算原理》一云计算
    如何在 CentOS 7 用 cPanel 配置 Nginx 反向代理
    安装PHP的memcache扩展
  • 原文地址:https://www.cnblogs.com/skylar/p/3992597.html
Copyright © 2011-2022 走看看