zoukankan      html  css  js  c++  java
  • 高性能javascript

    1、加载与执行

      由于多数浏览器使用单一线程来处理用户UI刷新和javascript脚本执行,所以同一时刻只能做一件事。这样就告诉我们js执行时间过程越久,浏览器等待响应的时间就越长,这里就存在一个性能问题,就是脚本的位置问题。

    由于脚本会阻塞页面渲染,所以只有js全部下载并且执行完成后才会渲染页面,那么我们期望js不要在页面渲染的时候进行加载。因此我们推荐的方式是:

    所有script标签尽可能的放到body标签的底部,以尽量减少对整个页面下载的影响。

    1、动态脚本元素

    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.onload = function(){//非IE
        alert('script loaded');
    };
    script.onreadystatechange = function(){//IE
        if(script.readyState == 'loaded' || script.readyState == 'complete'){
            script.onreadystatechange = null;
            alert('script loaded');
        }
    };
    script.src = 'file1.js';
    document.getElementsByTagName('head')[0].appendChild(script);
    onreadystatechange 有五个值:如下

    uninitialized
    初始状态
    loading
    开始下载
    loaded
    下载完成
    interactive
    数据完成下载但尚不可用
    complete
    所有数据已准备就绪
    动态加载脚本的兼容性写法
    function loadScript(url,callback){
        var script = document.createElement('script');
        script.type = 'text/javascript';
        if(script.readyState){//IE
            if(script.readyState == 'loaded' || script.readyState == 'complete'){
                script.onreadystatechange = null;
                callback();
            }
        }else{
            script.onload = function(){//非IE
                callback();
            };
        }
        script.src = url;
        document.getElementsByTagName('head')[0].appendChild(script);
    }

    使用方法如下:

    loadScript('file1.js',function(){
        alert('file is loaded!');
    });
    
    loadScript('file1.js',function(){
        loadScript('file2.js',function(){
            loadScript('file3.js',function(){
                alert('all files are loaded!');
            });
        });
    });

     XMLHttpRequest 脚本注入

    var xhr = new XMLHttpRequest();
    xhr.open('get','file1.js',true);
    xhr.onreadystatechange = function(){
        if(readyState == 4){
            if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
                var script = document.createElement('script');
                script.type = 'text/javascript';
                script.src = xhr.responseText;
                document.body.appendChild(script);
            }
        }
    }

    通过get请求一个js文件。 http状态码 2xx表示有效响应,304表示从缓存读取
    缺点是该代码不支持跨域,针对走cdn的文件不能采用这个方法

    动态加载js的通用工具可以在下面地址获取 

    https://github.com/rgrove/lazyload/     

    使用方法如下:

    LazyLoad.js('file1.js',function(){
        alert('file is loaded');
    });
    
    //按顺序加载多个文件
    LazyLoad.js(['1.js','2.js'],function(){
        alert('file is loaded');
    });

    第二种

    LABjs

    http://labjs.com/

    用法举例

    $LAB.script('file.js').wait(function(){
        //初始化
    });
    //lab script方法用来下载文件,wait方法用来指定文件下载并执行完毕后所调用的函数。支持链式调用
    $LAB.script('1.js')
        .script('2.js')
        .wait(function(){
            //初始化
        });

    前面的举例中1.js不一定会保证在2.js前调用。要保证这一点可以这么写

    $LAB.script('1.js').wait()
        .script('2.js')
        .wait(function(){
            //初始化
        });

    以上都是比较好的动态加载js的方式,且不会阻塞浏览器!

    例子和说明参考来自《高性能javascript》第一章

    事件委托


    当页面中存在大量元素的时候,要为每个元素绑定一个或多个事件处理程序,这种情况可能会影响性能!每绑定一次事件处理程序都是有代价的,它加重了页面的负担,增加了运行期间的执行时间。

    那么一个好的事件处理程序的技术是事件委托。它基于这样一个事实:事件是逐层向上冒泡并能被父元素捕获。使用事件代理只需给父元素绑定一个事件处理程序,就可以处理其子元素上触发的所有的事件。

    在IE下不支持捕获,但是只要支持冒泡就足够了!

    例如下面的例子:

    document.getElementById('main').onclick = function(e){
        e = e || window.event;
        var target = e.target || e.srcElement;
        var pageId,hrefparts;
        if(target.nodeName !== 'A'){
            return ;
        }
        hrefparts = target.href.split('/');
        pageId = hrefparts[hrefparts.length-1];
        pageId = pageId.replace('.html','');
        var xhr = new XMLHttpRequest();
        xhr.open('get','page.php?page='+pageId,true);
        xhr.onreadystatechange = function(){
            if(readyState == 4){
                if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
                    //更新页面
                }
            }
        }
        if(typeof e.preventDefault === 'function'){
            e.prenentDefault();
            e.stopPropagation();
        }else{
            e.returnValue = false;
            e.canceBubble = true;
        }
    }

    事件委托并不难,你只需要检查事件是否来自你所预期的元素,然后根据预期的元素来执行相应元素所绑定的事件处理程序。

  • 相关阅读:
    【Foreign】无聊的计算姬 [Lucas][BSGS]
    【Foreign】远行 [LCT]
    Leetcode题解(十)
    Leetcode题解(九)
    Leetcode题解(八)
    Leetcode题解(七)
    Leetcode题解(六)
    Leetcode题解(五)
    Leetcode题解(四)
    Leetcode题解(三)
  • 原文地址:https://www.cnblogs.com/shizhouyu/p/5209225.html
Copyright © 2011-2022 走看看