异步加载js
js加载的缺点:
加载工具方法没必要阻塞文档, 过多js加载会影响页面效率, 一旦网速不好, 那么整个网站将等待js加载而不进行后序渲染工作.
有些工具方法需要按需加载, 用到再加载, 不用不加载.
javascript异步加载的三种方案
1 . defer异步加载, 但要等到dom文档全部加载完才会被执行. 只有ie能用, 也可以将代码写到内部.
例
<script type = "text/javascript" src="##.js" defer="defer"></script>
2 . async异步加载, 加载完就执行, async只能加载外部脚本, 不能把js写在script标签里.
例
<script type = "text/javascript" src="##.js" aysnc="aysnc"></script>
3 . 创建script, 插入到dom中, 加载完毕后callBack
var script = document.createElement('script');
script.type = "text/javascript";
script.src = "tools.js";
if(script.readyState) {
script.onreadystatechange = function () {//ie
if(script.readyState == 'complete' || script.readyState == 'loaded'){
text();//某个函数
}
}
}else{
script.onload = function () {
text();
}
}
document.head.appendChild(script);
现在我们写个通用的异步加载函数.适用于ie和目前的通用浏览器.
注意: 我调整了script.src的位置, 因为如果数据量太小, 导致加载瞬间完成的话, 在if里面的语句是不会进行的, 因此我们先绑定事件然后再开始下载文件
/*
* 异步加载事件
* 2016.12.31
*/
function loadScript(url, callback){
var script = document.createElement('script');
script.type = "text/javascript";
if(script.readyState) {
script.onreadystatechange = function () {//ie
if(script.readyState == 'complete' || script.readyState == 'loaded'){
callback();//某个函数
}
}
}else{
script.onload = function () {
callback();
}
}
script.src = url;
document.head.appendChild(script);
}
再这里我们还需要注意一个问题
loadScript('tools.js', text);
如果我们这样运用函数可以吗, 答案是不可以的, 因为当解析到这一步时, 这里的text函数是在tools.js中定义的, 因此如果我们直接传text进去会发生未定义错误, 所以正确的使用上述函数的方法为.
loadScript('tools.ja', function() {
text();
});
js加载时间线
- 创建Document对象, 开始解析web页面, 解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中, 这个阶段document.readyState = ‘loading’.
- 遇到link外部css, 创建线程加载, 并继续解析文档.
- 遇到script外部js, 并且没有acync, defer, 浏览器加载, 并阻塞, 等待js加载完成并执行该脚本, 然后继续解析文档.
- 遇到script外部js, 并且设置有async, defer, 浏览器创建线程加载, 并继续解析文档, 对于async属性的脚本, 脚本加载完成后立即执行. (异步加载禁止使用document.write( )).
- 遇到img等, 先正常解析dom结构, 然后浏览器异步加载src, 并继续解析文档.
- 当文档解析完成, document.readState = ‘interactive’.
- 文档解析完成后, 所有设置有defer的脚本会按照顺序执行. (注意与async的不同, 但同样禁止使用document.write( ))
- document对象触发DOMContentLoaded事件, 这也标志着程序执行从同步脚本执行阶段, 转化为事件驱动阶段.
- 当所有async的脚本加载完成并执行后, img等加载完成后, document.readyState = ‘complete’, window对象触发load事件.
- 从此, 以异步响应方式处理用户输入, 网络事件.