seajs在IE9及以下的window.load事件调用失败

seajs在IE9及以下的window.load事件调用失败

          最近在在项目中遇到一个情况。项目使用seajs作为模块加载器,在js文件中的define回调中我们把函数都放在$(function () {})回调中去执行,意味着在文档加载完成后执行。

          但是这个页面是商品详情页,包含着大量的详情图片,众所周知,加载的图片都会影响最后的load时间。

seajs在IE9及以下的window.load事件调用失败

          就是最后红色的load时间,而这个时间的长短会影响页面加载旋转菊花的时间,seajs在IE9及以下的window.load事件调用失败

          而这个旋转菊花的转态非常影响用户体验(很多人看这个菊花转太久就直接走人了)

          为了体验上的改进,项目中的详情页的商品详情区块都采用异步加载的方式加载。

          但是在$(function () {})中异步加载商品详情区块并没有什么用,还是会影响最后的load时间。

          所以最后采用的是在define回调中使用window.onload方法,强制把商品详情区块在window.onload之后执行,这样加载的图片就不会影响load时间了。

addEventWhenOnload(window,'load',function(){
    // 更多活动信息加载
    new LoadActivity().init();
    // 商品详情信息加载
    new LoadDetails().init();
    new DetailTab().init();
})

在现代浏览器上很正常
seajs在IE9及以下的window.load事件调用失败

商品详情区块的图片都在红线之后加载(红线代表load时间)。

到这应该就圆满结束了。

          但是万恶的IE8、IE9的问题又出来了。在IE8/IE9下异步加载的区块都没执行了。相应的页面中详情图片区块都空了。

一番搜索之后,问题找到了seajs上。

          seajs模块加载器的实现方法是动态的生成一个script,然后对这个script设置async属性。

          对这个async属性做个简单的介绍,就是这个外部脚本不会阻塞domtree的构建,异步下载,一旦下载就会执行。
具体的可以看我翻译的一篇文章
http://lvdada.org/2015/11/12/%E7%A0%B4%E8%AF%91%E5%85%B3%E9%94%AE%E6%B8%B2%E6%9F%93%E8%B7%AF%E5%BE%84%EF%BC%88%E7%BF%BB%E8%AF%91%EF%BC%89/

          这个机制本来对于我们之前的方案也没有影响,即使
seajs在IE9及以下的window.load事件调用失败
item-detail.js这个异步脚本会在蓝线之后再加载执行,但是jquery的$(function () {})的实现会判断目前文档是否到了domready状态,若执行的时候已经过了domready状态,就会立即执行。

但是async只支持IE10及以上!

          就是这个问题,在IE8、9浏览器上加载标有了async的外部脚本会什么时候开始加载执行呢,我们看实际的timeline。

seajs在IE9及以下的window.load事件调用失败

          黄框就是加了async的脚本的加载执行时间,注意看图,加载的时间在load之后。

          现在就能清晰的知道原因了,业务js脚本在IE8/9下在load之后才加载,那在脚本中绑定的window.onload事件肯定就绑定不到了。

总结

在seajs中还是慎用window.onload啊。。

相关推荐