• window.onload加载的多种解决方案


    使用JavaScript操纵DOM,必须等待DOM加载完毕才可以执行代码,但window.onload有个坏处,它非要等到页面中的所有图片及视频加载完毕才会触发load事件。结果就是一些本来应该在打开时隐藏起来的元素,由于网络延迟,在页面打开时仍然会出现,然后又会突然消失,让用户觉得莫名其妙。我们想做的就是寻找一种方法来确定DOM被完全的加载时不用等待所有那些讨厌的图片加载完毕。必须与这种丑陋的闪烁告别!

    我这里整理出针对onload事件的七种方案。

    第七种方案是我们最终的解决方案,也是完美的解决方案。

    三 ~ 六 的解决方案只解决了window.onload加载多个方法,但是还没有解决图片的等待加载问题,还有它们只兼容IE和FF。

    定义和用法 
    onload 事件会在页面或图像加载完成后立即发生。

    语法

    onload=”SomeJavaScriptCode”

    支持该事件的 HTML 标签:

    1
    <body>, <frame>, <frameset>, <iframe>, <img>, <link>, <script>

    支持该事件的 JavaScript 对象:

    image, layer, window实例

    第一种:

    1
    2
    3
    function loadFunction(){   
      alert("hello!");
    }

    1
    <body onload="loadFunction()">

    第二种:

    1
    2
    3
    4
    window.onload = loadFunction;   
    function loadFunction(){   
    alert("hello!");
    }

    第三种:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function firstFunction(){
    alert("hello firstFun !");
    }
    function secondFunction(){
    alert("hello secondFun !");
     
    }
    window.onload = function(){   
       firstFunction();   
       secondFunction();   
    }

    第四种:通用的做法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    function firstFunction(){
    alert("hello firstFun !");
    }
    function secondFunction(){
    alert("hello secondFun !");
     
    }
     
    function addLoadEvent(func) {   
      var oldonload = window.onload;   
      if (typeof window.onload != 'function') {   
          window.onload = func;   
      } else {     
          window.onload = function() {   
             oldonload();   
             func();   
          }   
      }   
    }  
     
    //测试  
    addLoadEvent(firstFunction);
    addLoadEvent(secondFunction);

    addLoadEvent工作流程:

    把现有的window.onload事件处理函数的值存入变量oldonload。

    如果在这个处理函数上还没有绑定任何函数,就像平时那样把新函数添加给它;

    如果在这个处理函数已经绑定了一些函数,就把函数追回到现有指令未尾。

    浏览器加载html内容是自上而下的(默认),而JS一般是在哪里引入——想想如果JS里面包含了一些即时执行指令,

    它会操作根本不存在元素节点(因为还没有加载完)会有什么后果?结果就是出错。

    addLoadEvent可以实现无论有多少个函数,都能让它们同时和window.onload事件绑定。

    第五种; 推荐

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    function a(){   
      alert("a");   
    }   
     
    function b(){   
      alert("b");   
    }
     
     
    function addEvent(obj,EventName,callBack){//给对象添加事件   
      if(obj.addEventListener){   //FF
         obj.addEventListener(EventName,callBack,false);   
      }else if(obj.attachEvent){//IE   
         obj.attachEvent('on'+EventName,callBack);   
      }else{   
         obj["on"+EventName]=callBack;    
      }   
    }    
    //测试  
    addEvent(window,"load",a);   
    addEvent(window,"load",b);

    第六种:推荐

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    function a(){   
     alert("a");   
    }   
     
    function b(){   
     alert("b");   
    }
    // Please note: this file contains snippets for comparison   
    // it is not self-contained or ready-to-use code as such     
    function addLoadListener(fn)   
    {   
       if (typeof window.addEventListener != 'undefined')  
       {   
       window.addEventListener('load', fn, false);   
       }   
       else if (typeof document.addEventListener != 'undefined')   
       {   
       document.addEventListener('load', fn, false);   
       }   
       else if (typeof window.attachEvent != 'undefined')
       {   
       window.attachEvent('onload', fn);   
       }   
       else  
       {   
       var oldfn = window.onload;   
       if (typeof window.onload != 'function')   
       {   
       window.onload = fn;   
       }   
       else  
       {   
       window.onload = function()   
          {   
          oldfn();   
          fn();   
          };   
       }   
      }   
    } 
     
    //测试
    addLoadListener(a);
    addLoadListener(b);

    第七种:最完美的解决方案

    建立一个独立的通用解决方案,兼容各种浏览器,任何人都可以使用,而无需一个具体的框架。

    最初的完整解决方案:http://dean.edwards.name/weblog/2006/06/again/

    一个独立的通用解决方案 :http://www.thefutureoftheweb.com/blog/adddomloadevent.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
     
    /*
     * (c)2006 Jesse Skinner/Dean Edwards/Matthias Miller/John Resig
     * Special thanks to Dan Webb's domready.js Prototype extension
     * and Simon Willison's addLoadEvent
     *
     * For more info, see:
     * http://www.thefutureoftheweb.com/blog/adddomloadevent
     * http://dean.edwards.name/weblog/2006/06/again/
     * http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
     * http://simon.incutio.com/archive/2004/05/26/addLoadEvent
     * 
     *
     * To use: call addDOMLoadEvent one or more times with functions, ie:
     
     * addDOMLoadEvent的调用方法,如下:
     *    function something() {
     *       // do something
     *    }
     *    addDOMLoadEvent(something);
     *
     *    addDOMLoadEvent(function() {
     *        // do other stuff
     *    });
     *
     */
     
    addDOMLoadEvent = (function(){
     
        // create event function stack
        var load_events = [],
            load_timer,
            script,
            done,
            exec,
            old_onload,
            init = function () {
                done = true;
                 /*//停止调用计时器*/
                // kill the timer
                clearInterval(load_timer);
     
                // execute each function in the stack in the order they were added
                while (exec = load_events.shift())
                    exec();
     
                if (script) script.onreadystatechange = '';
            };
     
        return function (func) {
            // if the init function was already ran, just run this function now and stop
            if (done) return func();
     
            if (!load_events[0]) {
     
                // for Mozilla/Opera9
       /* 
           DOMContentLoaded是firefox下特有的Event, 当所有DOM解析完以后会触发这个事件。
          注册DOMContentLoaded事件,如果支持的话
       */
                if (document.addEventListener)
                    document.addEventListener("DOMContentLoaded", init, false);
     
                // for Internet Explorer
       /*
         对于IE则使用条件注释,并使用script标签的defer属性
                  IE中可以给script标签添加一个defer(延迟)属性,这样,标签中的脚本只有当DOM加载完毕后才执行*/
     
                /*@cc_on @*/
                /*@if (@_win32)
                    document.write("<script id=__ie_onload defer src=//0><\/scr"+"ipt>");
                    script = document.getElementById("__ie_onload");
                    script.onreadystatechange = function() {
                        if (this.readyState == "complete")
                            init(); // call the onload handler
                    };
                /*@end @*/
     
                // for Safari
          /*
        但对于Safari,我们需要使用setInterval方法不断检测document.readyState
                 当为loaded或complete的时候表明DOM已经加载完毕 
       */
     
                if (/WebKit/i.test(navigator.userAgent)) { // sniff
                    load_timer = setInterval(function() {
                        if (/loaded|complete/.test(document.readyState))
                            init(); // call the onload handler
                    }, 10);
                }
     
                // for other browsers set the window.onload, but also execute the old window.onload
                old_onload = window.onload;
                window.onload = function() {
                    init();
                    if (old_onload) old_onload();
                };
            }
     
            load_events.push(func);
        }
    })();

    方案七的演示:

  • 相关阅读:
    如何心无旁鹜的编程
    [转]虚拟现实和现实增强技术带来的威胁
    Mac上好用软件集锦
    无论如何都要来报到
    Unity3D脚本语言UnityScript初探
    X3DOM新增剪裁平面节点ClipPlane支持
    用Perl编写Apache模块续二
    如何浪费自己青春
    macbook 我们需要买吗
    看了一本Unity3D的教程
  • 原文地址:https://www.cnblogs.com/xx_cs/p/2143406.html
Copyright © 2020-2023  润新知