HTML DOM Script 对象对addEventListener支持试验

这是一个很基础的问题,以前没有仔细想过,直到实际工作中才知道。
Script 对象 原则上也属于dom对象,在w3文档中,是这样写的:Script 对象同样支持标准 属性 和 事件。

实际使用中,发现对于事件绑定的支持,是有条件的。

对于普通的dom对象,我们可以使用addEventListener来绑定事件,如下:

    document.getElementById('test2').addEventListener('click', function(){
        alert('error2')
    })

 

但是实际上,按照下面的写法对script Object绑定事件是不会起作用的,下面的例子就算加js载失败,也是不会走进onerror:

<script type="text/javascript" id="test2" src="test2.js"></script>
<script>
    document.getElementById('test2').addEventListener('error', function(){
        alert('error2')
    })
</script>

后来发现,必须给script 加上 async,可以不用设置true;

<script type="text/javascript" async id="test2" src="test2.js"></script>
<script>
    document.getElementById('test2').addEventListener('error', function(){
        alert('error2')
    })
</script>

或者如下方法异步加载js:

var sc = document.createElement('script');
sc.setAttribute('src', 'test.js');
sc.setAttribute('async', true);
sc.onload = function(){

}
sc.addEventListener('error', function(){
console.log('error')
alert('error')
})
document.getElementsByTagName('head')[0].appendChild(sc)

 

那么,为什么呢,首先我们来看看async的属性

async 属性规定一旦脚本可用,则会异步执行。

注释:async 属性仅适用于外部脚本(只有在使用 src 属性时)。

注释:有多种执行外部脚本的方法:

通俗一点讲:

没有 defer 或 async,浏览器会默认为同步sync,会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。

有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。

有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。

也就是说,在没有使用async,也不使用 defer时,在浏览器继续解析页面之前,立即读取并执行脚本了。
这个时候,如果再使用类似document.getElementById(‘test2’).addEventListener方式来监听load或者error事件,其实是监听不到的。
有人说放到前面行不行,放前面理论上是可以,但是document.getElementById(‘test2’) 在此js加载之前 也是拿不到到的。
所以结论就是,这种情况下,addEventListener does not work。

因此,如果我们的js脚本必须同步加载和执行这种情况下,不能使用addEventListener来监听事件了,但是可以这样:

<script type="text/javascript" src="xxx.js" onload="handleLoad"></script>
<script type="text/javascript">
var handleLoad = function(){
    // to do something
}
</script>

发表评论

记录工作生活点滴。

返回
顶部