【前端知识点】IE下script标签的readyState属性


在做加载器时遇到一个常见问题,如何判定一个脚本已经执行完毕。

  • “uninitialized” – 原始状态
  • “loading” – 下载数据中
  • “loaded” – 下载完成
  • “interactive” – 还未执行完毕
  • “complete” – 脚本执行完毕.

网上流行的答案是这个,我怎么觉得其实这是抄自XMLHttpRequest的readyState呢?!恰逢这两个都有这属性。

我们亲自做一个实验:

<! DOCTYPE  html>
< html >
     < head >
         < title >node.readyState</ title >
         < meta  charset="UTF-8">
         < meta  name="viewport" content="width=device-width">
         < script >
             var node = document.createElement("script")
             node.onreadystatechange = function() {
                 var state = node.readyState
                 setTimeout(function() {
                     var div = document.createElement("div")
                     document.body.appendChild(div)
                     div.innerHTML = state
                 }, 300)
 
             }
             var head = document.getElementsByTagName("head")[0]
             head.appendChild(node)
             node.src = "avalon.js"
 
         </ script >
     </ head >
     < body >
         < div >node.readyState</ div >
     </ body >
</ html >
完整的控件教程
IE11空白,说明完全与标准一致了
IE10loading loaded
IE9loading loaded
IE8complete loaded
IE7complete loaded 但有一定机率,只出现complete或loaded
IE6complete loaded 但有一定机率,只出现complete或loaded

换言之,IE67是个非常悲催的问题。另外,opera9-10也支持readyState,根据老外的描述,它竟然两次都是loaded!

因此我们需要根据浏览器的情况采用不同的策略。

首先是使用何种回调,如果是支持onload事件,那么就直接用onload 就没有这么多麻烦事。最简单的策略是这样判定:

var  node = DOC.createElement( "script" )
var  supportLoad = "onload"  in  node
var  onEvent = supportLoad ? "onload"  : "onreadystatechange"
node[onEvent] = callback

判定完成时机, 我们不使用网上的/complete|loaded|undefined/.test(node.readyState),这会同时掉进opera与IE67的坑中。对于使用onload事件进行监听的,不再判定node.readyState,IE(其实也就是IE6-8),需要使用一个定时器。当第一次进行onreadystatechange回调时,timeID为空, 并且readyState为complete或loaded时,我们设置它在300ms后再执行自身。然后如果浏览器还执行此回调时, 它就进入第二个分支,清掉定时器,执行用户代码。万一,浏览器只执行一次onreadystatechange回调,那也没关系,让定时器100~300ms后执行用户代码

最后贴出全部代码:

//通过script节点加载目标模块
var  node = DOC.createElement( "script" )
var  timeID
var  supportLoad = "onload"  in  node
var  onEvent = supportLoad ? "onload"  : "onreadystatechange"
node[onEvent] = function  onLoad() {
     if  (!supportLoad && !timeID && /complete|loaded/.test(node.readyState)) {
         timeID = setTimeout(onLoad)
         return
     }
     if  (supportLoad || timeID) {
         clearTimeout(timeID)
         //你的代码
     }
}
 
head.insertBefore(node, head.firstChild) //chrome下第二个参数不能为null
node.src = url //插入到head的第一个节点前,防止IE6下head标签没闭合前使用appendChild抛错

大家也可以到这里看一下它的实际应用,如果大家都是使用AMD规范定义JS文件,那么我在旧式IE下连onerror也模拟出来了。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值