window.onload与DOM树

    先看一下问题:

1  window.οnlοad=function(){
2        createDom();
3        operateDom();
4        //code stuff
5  }
     其中 createDom()通过异步请求取得大量数据,然后组织起来;operateDom()是通过遍历操作createDom生成的节点。问题出现了:页面显示的并不是我们想要的效果。为什么?operateDom并不能总是取到生成的dom节点。由于生成的dom节点附加到页面dom树的时候存在着延迟,所以在createDom里面数据量比较大、生成dom节点比较多的时候,这种时间差会很大(对机器而言)。虽然createDom里面的语句执行完毕,接下来执行operateDom,但那些生成的节点也许还没有完全附加到dom树上面,所以就存在取不到dom节点的情况。
    也许你会想,为什么不直接在createDom里面在生成那些dom的时候直接操作,而是重新进行遍历操作?问题在于createDom和operateDom并不是同一个开发人员写的,也有可能是调用公用的东西,所以更不可能去改createDom了。这里只是为了举例方便。
    怎么办?setTimeout?setTimeInterval?
    setTimeout自然不可取,我们并不知道时间差是多少,设的太长了,用户体验不好,设的太短了,达不到我们的目的。setTimeInterval可以,但这会频繁的执行,我们只需要它执行一次。针对setTimeInteval,折中的解决办法是设置哨位监视。改动一下:
1  operateDom(){
2      if(operateDom.called)
3         return;
4      // code stuff
5  }
    问题解决了?没有。我们要操作的是Dom,onload会直到页面所有内容都加载完成才执行。如果页面有太多的图片,那就只用等了。对用户来说,等的时间就是加载图片的时间,然后加上我们处理dom节点的时间,用户体验就差了。我们需要的仅仅是dom加载完成!
    对Mozilla系列的浏览器(如ff/googlechrome),可以:
1  // for Mozilla browsers
2  if (document.addEventListener) {
3     document.addEventListener("DOMContentLoaded", init, false);
4  }
    其中init执行createDom和修改后的operateDom.下同。
    IE支持条件编译(js是解释执行的,这里找不到合适的词来表述,看下面的代码就知道了)。在IE系列的浏览器中,可以:
ContractedBlock.gif ExpandedBlockStart.gif Code
1  // for Internet Explorer
2  /*@cc_on @*/
3  /*@if (@_win32)
4    document.write("<script defer src=ie_onload.js><"/script>");
5  /*@end @
    如果在页面里面这么写:
ContractedBlock.gif ExpandedBlockStart.gif Code
<!--[if IE]><script defer src="ie_onload.js"></script><![endif]

 1 function init() {
 2    // quit if this function has already been called
 3    if (arguments.callee.done) return;
 4  
 5    // flag this function so we don't do the same thing twice
 6    arguments.callee.done = true;
 7  
 8    createDom();
 9    setTimeInterval("operateDom()",100);
10    //code stuff
11 
    在IE系列的浏览器是正常的,其它浏览器会忽略defer属性,将外部js文件加载进来。这里ie_onload.js里面只有init函数。 对其它系列的浏览器,这么写: window.οnlοad=init. 综合起来,init就会执行多次了,就不是一次。同上面处理operateDom一样,给init增加一个哨位即可:     1 function init() {
 2    // quit if this function has already been called
 3    if (arguments.callee.done) return;
 4 
 5    // flag this function so we don't do the same thing twice
 6    arguments.callee.done = true;
 7 
 8    createDom();
 9    setTimeInterval("operateDom()",100);
10    // do stuff
11  };

   至此,问题解决。

参考资料:The window.onload Problem - Solved!





转载于:https://www.cnblogs.com/huankfy/articles/1285759.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值