JavaScript页面文档初始化 window.onload的替代办法

很早,大概去年就在mg12的博客看到他一篇很久以前的文章《 JavaScript 初始化装载方法 》,当时也没注意。这两天在做页面一些部分的延迟加载时,又想起了这个,因为使用window.onload,实在是一个很不明智的选择,很可能一个坏掉的图片或什么的就会导致你的JS迟迟装载不了,无法执行。

我试用了一下mg12文章中的方法,发现一个严重的错误,那就是在IE下如果同时绑定多个函数,那么就只会有最后一个执行。仔细分析了一下,原来是因为代码中判断IE页面文档初始化完毕时会向页面中写入一个

   1: <script id="__ie_onload" defer src="javascript:void(0)"></script>

而绑定多个函数时,就会向页面中写入多个上面的标签,由于页面上只允许一个id存在,所以通过document.getElementById(“__ie_onload”);自然就只能获得一个对象,所以只会执行一个绑定函数了。

我对其稍微进行了改造,无非就是加个数值变量,每次写入时让ID不同。

   1: var _flag=1;//标志整型变量
   2: function documentReady(fun){
   3:     if (document.addEventListener) {
   4:         document.addEventListener("DOMContentLoaded", fun, false);
   5:     } else if (/MSIE/i.test(navigator.userAgent)) {
   6:         document.write('<script id=__ie_onload'+_flag+' defer src=//0><\/script>');
   7:         var script = document.getElementById("__ie_onload"+_flag);_flag++;
   8:         script.onreadystatechange = function() {
   9:             if (this.readyState == 'complete') {
  10:                 fun();
  11:             }
  12:         }
  13:     } else if (/WebKit/i.test(navigator.userAgent)) {
  14:         var _timer = setInterval( function() {
  15:             if (/loaded|complete/.test(document.readyState)) {
  16:                 clearInterval(_timer);
  17:                 fun();
  18:             }
  19:         }, 10);
  20:     }
  21: }

这样如果绑定多个函数,就会在页面上依次写入id=”__ie_onload1”、id=”__ie_onload2”。。。等<script>标签了。

如此一来,即使绑定多个函数也可以顺利执行了。

后话:今天闲暇时,又上网搜了一下这方面的东西,发现早在06年就有人贴出了几近完美的解决方法,而且他们也考虑到了多个事件函数执行的问题,通过栈结构解决的。它是将绑定的所有函数存入一个栈中,判断文档下载完成后,再从栈中依次取出函数执行,相比于我上面的方法,判断文档是否完成只需要一次即可,无论绑定了多少个函数都是只需一次,而我的就需要多次了。看样子mg12看的书貌似是抄袭人家的,也不知为何进行了精简,结果还给精简错了,囧。。原始网页在http://www.thefutureoftheweb.com/blog/adddomloadevent,有兴趣围观。

下面是文章的代码去掉注释后

   1: addDOMLoadEvent = (function(){
   2:     var load_events = [],load_timer,script,done,exec,old_onload,
   3:         init = function () {
   4:             done = true;
   5:             clearInterval(load_timer);
   6:             while (exec = load_events.shift())
   7:                 exec();
   8:             if (script) script.onreadystatechange = '';
   9:         };
  10:     return function (func) {
  11:         // if the init function was already ran, just run this function now and stop
  12:         if (done) return func();
  13:         if (!load_events[0]) {
  14:             // for Mozilla/Opera9
  15:             if (document.addEventListener)
  16:                 document.addEventListener("DOMContentLoaded", init, false);
  17:             // for Internet Explorer
  18:             /*@cc_on @*/
  19:             /*@if (@_win32)*/
  20:             if (/MSIE/i.test(navigator.userAgent)){
  21:                 document.write("<script id=__ie_onload defer src=//0><\/scr"+"ipt>");
  22:                 script = document.getElementById("__ie_onload");
  23:                 script.onreadystatechange = function() {
  24:                     if (this.readyState == "complete")
  25:                         init(); // call the onload handler
  26:                 };
  27:             }
  28:             /*@end @*/
  29:             // for Safari
  30:             if (/WebKit/i.test(navigator.userAgent)) { // sniff
  31:                 load_timer = setInterval(function() {
  32:                     if (/loaded|complete/.test(document.readyState))
  33:                         init(); // call the onload handler
  34:                 }, 10);
  35:             }
  36:             old_onload = window.onload;
  37:             window.onload = function() {
  38:                 init();
  39:                 if (old_onload) old_onload();
  40:             };
  41:         }
  42:         load_events.push(func);
  43:     }
  44: })();

具体的效果,可以到我的友情链接页面查看。这个页面有许多favicon图标需要从不同的地址下载,需要时间较长,而使用本文中的初始化装载方法后,并不会因为图标的未下载而影响我js代码的执行。大家可以很顺利的看到边栏各个栏目被加载上(:边栏应用了延迟加载)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值