异步加载
说到异步,那么什么叫做异步加载呢?
刚开始的时候,也简单的说聊了一下什么叫做异步。大致的因该知道异步是用来做什么的了,就是为了充分了利用js引擎,是页面更快的加载而已。那么具体如何实现异步的,又为什么要使用异步操作,那么接下来在详细的说明一下。
在正式的说明之前,先说一个小的知识点。
JSON
大家可能知道JSON是什么东西,它是以数据的一种形式,用来作为数据的传输的。
数据传输的方式:
xml和JSON。
xml
是
html
的模板,自定义标签名作为数据名来传输数据,书写是比较麻烦的,现在大部分的都在用json格式的。
json是数据传输的一种格式,它是以对象为模板(其实它就是一个对象而已,但是还是有一些区别的,对象只能在班底上,而json是传递数据用的。)
当我们把数据给传输过去的时候,数据只是一种json的格式,必须转化成对象的模式,在本地才能使用的。那么就用到了JSON上的两种方法了(JSON.parse()、JSON.stringfy())
var obj1 = {
name: "si",
age: 18
}
var string1 = JSON.stringify(obj1);
var string2 = JSON.parse(string1)
console.log(string1)//将对象转化成JSON格式的
console.log(string2)//将JSON格式的转化成对象
经过这两种方法的转化,我们可以接受后台给的数据,也能将数据传给后台,实现了数据的交互。
JS异步加载部分
我们应该知道script标签有阻塞DOM解析的作用,只有script下载结束之后并且等执行结束后,才能进行下面的DOM解析。
如果这样的话就会导致一些不便了:本身这一块的功能不是太大,有可能在用户打开的时候根本就用不到的,结果就给阻塞在这里,导致以后的页面加载不出来。如果网不好的情况下,就会导致一个卡顿,可能会看着很不舒服的。那么我们得有办法来解决这个问题呀,我们就分析一下这个原因:
DOMTree是来解析DOM来用的,当页面在解析DOM的时候,中间突然加上一个script标签,这样会导致DOMTree和CSSTree解析暂时停下来,先把script标签加载完毕之后,在进行接下的操作。这个时候我们就要加入一些东西了,让这个标签异步加载或者是说按需加载,就会解决这个问题了。
之前我们在写demo时候都把script标签都写在后面,这样就没有上面的影响了。
那呢接下来,就介绍一下js的异步加载:
1.
defer
我们在script标签的行间写一个defer=“defer”或者直接写defer,就可以让这个script变成异步加载了。但是这种异步只是针对下载方面,只有等DOMTree全部解析完成(不包括下载完里面的资源)后才会异步执行。而且这个方法只有IE和一些高版本的firefox和chrome可以用。
<script type="text/javascript" defer>
function test(){
console.log('123');
}
</script>
当然里面也可以外部引入,用个src,这样就可以引入外部文件的js了。
IE6和IE7的异步加载最多只能有2个,当多余两个的时候必须等前两个加载完才会加载第三个。
所有defer的js代码都保证按照顺序执行。
defer(延迟)是html4.0中定义的,该属性使得浏览器能延迟脚本的下载,等document文档载入和解析完成后,按照他们在文档中出现顺序再去下载解析。也就是说defer属性的<script>就类似于将<script>放在body底部的效果,会在document的DOMContentLoaded事件之前执行。
2.async异步加载
async(异步)是HTML5新增的属性,该属性的作用是让浏览器能并行下载脚本且不阻塞浏览器的文档解析和渲染,下载完成后脚本立即执行,可能无序执行,取决于下载完成的时间,这个异步相对来说比较强大一些,但是兼容s性的问题,必须支持html5的浏览器才能使用这个属性的。
<script type="text/javascript" async></script>
既然说到这个了,那么就说一下它们的区别吧:
(1)每一个async属性的脚本一旦加载完毕就会立刻执行,一定会在window.onload之前执行,但可能在document的DOMContentLoaded之前或之后执行。不保证按照指定它们的顺序来执行,如果JS有依赖性就要注意了。指定异步脚本的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容,因此,建议异步脚本不要在加载期间修改DOM。
(2)每一个defer属性的脚本都是在文档元素完全载入后,一般会按照原本的顺序执行,同时一般会在document的DOMContentLoaded之前执行,相当于window.onload,但应用上比 window.onload 更灵活!实际上,defer 更接近于DomContentLoad。事实上,延迟脚本不一定会按顺序执行,也不一定会在DOMContentLoaded事件触发之前执行,因此最好只包含一个延迟脚本。
DOMContentLoaded与load的区别。前者是在document已经解析完成,页面中的dom元素可用,但是页面中的图片,视频,音频等资源未加载完,作用同jQuery中的ready事件;后者的区别在于页面所有资源全部加载完毕。
那么问题就来了,defer(延迟)这个属性跟window.onload,到了最后再进行加载页面,不会阻塞onload,但是,这个async属性,如果异步加载的没有加载完,会导致了,onload无法触发,因此会阻塞。
解决方法:
(function(){
if(window.attachEvent){
window.attachEvent("load", asyncLoad);
}else{
window.addEventListener("load", asyncLoad);
}
var asyncLoad = function(){
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
}
}
)();
这个方法先等到文档解析完成之后,在触发onload,在进行异步加载js,不会影响页面的卡顿了,这样也优化了界面,提高了性能。
3.动态创建script标签
在没有定义defer和async之前,异步加载的方式是动态创建script,通过window.onload方法确保页面加载完毕再将script标签插入到DOM中。
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function(){
addScriptTag("js/index.js");
}
这个动态创建之后,一定要把这个标签放在onload里面,刚才也说到了,如果不放在这里面,会阻塞页面也就达不到我们想要的结果了。
今天对异步操作又有了深刻的理解,同时也看了一些大神们写的资料。感觉自己以前了解的还是不够多。