14 js09 json 异步加载 js时间线

1、json: 轻量级的数据交换格式;[前后端数据传输都是json格式的,对象里面的键必须要有双引号,不可省略;传输过程中json是以字符串进行传输的,直接对象形式传输不可以,其识别的是二进制,所以传输过程中使用的是二进制的文本格式即字符串]

(1).xml: 其是一种语言(xml ->xhtml ->html),最初也作为数据交换格式使用,其以标签作为数据名,标签内容作为数据值进行传递数据,其可以自定义标签,传输效率低下,如今大多使用json;[前后端通信传递数据是以字符串的形式进行,字符串内填充数据,而且数据就是对象的形式,前端给后端传递数据,传递的是字符串类型的数据,后台收到进行解析成对象再进行一系列的操作(类如:表单数据收集),同理后台传递给前端的数据也是字符串格式,需要转化为对象] [传递数据需要高效、便捷]

(2).json 是以对象为样板,本质上就是对象,在js中“一切都是对象”,但其和对象的用途上有区别,对象是本地使用(浏览器端、服务器端),json是用来传输的,形式上也有区别,json中的属性必须加双引号,不可省略;对象中双引号可以省略【区分json和对象的要点】

json数据:var obj = { "name": "abc","age": 18};json字符串:"{ "name": "abc","age": 18}"

(3).以下这两个方法很重要:进行解析数据的第一步【JSON、Math都是静态类,使用过程中不能new +构造函数创建对象使用;其上有很多属性和方法,直接使用就OK】

JSON.stringify();   json  --->>> string;   JSON.parse();   string  --->>> json;

[var obj = {name:"nba",age:18} --->> JSON.stringify(obj); -->> "{ "name": "nba","age": 18}", json本质也是对象,目前JSON操作时也识别为json对象]

2、异步加载:前面谈到html和css是异步加载,js是同步加载,加载到js部分阻塞页面的加载直到js加载完成,所谓异步加载:工具类/数据初始化的js脚本库异步加载,操作dom元素的js脚本进行同步加载即可;(操作dom元素的js脚本若是异步加载,每次改动必然会影响domTree,进而影响randerTree,耗费性能); 【js是单线程,若是双线程,一个线程增加dom元素,一个线程删除dom元素,执行哪个?

浏览器内核中有渲染引擎和js引擎,渲染页面的过程是怎样的?html、css、js文件执行顺序是怎么样的呢?

头部引入的css文件和html是异步线程执行,引入的js文件和html是同步执行:js文件加载完成后,html才能接着进行解析,也就是js会阻塞后面的dom解析(若遇到网速不好等情况,整个网站将等待js库加载而不进行后续渲染);日常开发中,一些工具类的js库、引入的第三方库,我们希望其可以同时进行加载,没必要阻塞dom解析,影响页面效率,最好采用异步加载的方式;

(1).接下来先分析一些页面渲染过程:(结合原生js小结图示过程)

[1].渲染引擎是一行行(按像素点)进行渲染页面的,代码中就是一行行执行代码(当然并非视觉编程的顺序,有预编译过程),首先它会进行domTree的绘制,遵循“深度优先原则”,渲染dom的过程中,若是存在一些Img标签、a标签等含有src、href属性,和css样式有所关联的,内部依旧会继续解析dom元素到domTree上,但css相关样式也开始绘制;

[2].domTree树绘制完成后,cssTree的绘制是同时进行的,[1]中只是绘制相关元素的位置,现在开始绘制和domTree有关的所有样式;

[3].cssTree树绘制完成后,其和domTree会进行结合形成渲染树,domTree + cssTree = renderTree; 有了renderTree后,渲染引擎才开始按着它开始渲染页面;

[4].期间<head></head>标签部分引入的js文件,其会阻塞页面的渲染过程,这里还需要介绍两个重要概念:reflow 、 repaint;

        [4.1] js可以操作html,进而也可以间接操作css,每一次操作都会对domTree产生影响,domTree一变化,就需要重新绘制domTree、cssTree,这种改变称为reflow重排(重构、重做),很影响性能,这也是我们不要随便修改html结构的原因[常见可引起重构的行为:dom节点的删除增加、dom元素的宽高变化、位置变化,display:none -->>> display: block; 改变某个元素会对后续元素产生一系列影响; offsetWidth  offsetHeight 这两个虽是查看元素,但依旧会对dom元素产生影响]

        [4.2]repaint 重绘,其区别于reflow,只需要进行部分domTree重绘即可,大多是一些样式的微弱改变,不影响html结构,例如字体颜色、背景图片、背景颜色等等,对后续元素也无影响,对性能也有影响,但很小;

(2).JS异步加载的三种方法:操作dom元素的还是采取同步加载,对于工具库/初始化数据的库,采取异步加载或者按需加载来提高页面效率;

[1].defer异步加载,只有IE9以下可用,在script标签加入单属性即可;                                               <script type="text/javascript" scr="tools.js" defer="defer"></script>; 其不仅可以引入外部文件,也可以将代码写入内部,<script type="text/javascript" defer="defer">console.log('a');<script>; [不要既引入外部,又在内部写代码]  缺点:虽然可以同时进行加载,但必须等到dom文档全部解析完才会被执行;【注意:IE6和IE7的异步加载最多只能有2个,当多余两个的时候必须等前两个加载完才会加载第三个】

[2].async ,w3c标准,(IE9以下不兼容);<scrip type="text/javascript" src="tools.js" aysnc="aysnc" ></script>; 其只能加载外部脚本,不能把js代码写在内部,同时其是加载后就执行;

如何处理兼容性:封装在任何浏览器都能异步加载脚本库;

方法一:<script type="text/javascript" aysnc="aysnc" src="tools.js" defer="defer"><script>  ,这种方法不可以,容易引起系统崩盘;

方法二:<script type="text/javascript" aysnc="aysnc" src="tools.js"><script>

<script type="text/javascript" defer="defer" src="tools.js"></script> 这种方式也不合理;

--->>> 开发中采取的方法:进行if判断,if(IE){使用defer}else{使用async}

[3].按需加载:异步加载并且按需加载,什么时候用到该脚本,什么时候进行加载,不用就不用管它;应用场景也很多,例如:有的按钮用户很少会点击,但却有产品价值,而且点击有可能会出现很多信息,可以对其进行“按需加载”,用户点击的时候动态加载完毕即可,不一定执行到该脚本库就阻塞页面或异步加载;

按需加载才是最合适的异步加载方案:创建script,插入到html中,加载完毕后callBack;(内容较多,附详细过程)

[3.1]. 重点:创建script标签后,添加script.src="tools.js"时,只是进行异步加载,并没有执行;

-------->>>>>>>代码跑起来的时候会报错,下载资源需要过程:发出请求,等待响应,响应后开始反馈资源,期间过程是以微秒(us)计算,由于是异步加载,下面的代码在加载过程中便开始执行,执行过程中若是找不到该方法便会报错;错误原因:加载时间大于代码执行时间;

[3.2]使用定时器验证上述说法:

-------->>>>>代码可以正常运行,加载的时间受很多因素影响,例如网速不好等,接下来进行一些操作解决bug,等其加载完成后再执行代码;

[3.3].load事件,很多对象都有load事件,并非window独有(涉及到下载的就有load事件);表示:下载完成后触发事件,兼容性很好,safari/chrome/firefox/opera都兼容,IE浏览器也有load事件,但IE中的script标签上没有load事件;

[3.4].IE使用: readystatechange事件,IE在script上设置了状态码readState,随着加载过程其的属性值会变化;开始:script.readyState = "loading",--->>>加载完成后:script.readyState="complated" /  script.readyState="loaded";[IE和高版本的chrome、firefox的script有此事件,但是其他浏览器的dom元素上也有此事件和属性;document.readyState,表示状态]

[3.5]封装兼容性函数:url:引入的脚步库,callback(); 回调函数,当满足一定条件才执行的函数;将script.src=url;换位置的原因是解决bug,防止IE无法判断,解释:IE判断的标准就是script的状态码是否发生变化,若是代码执行到script.src=url; 加载速度特别特别快,在执行下面的判断语句前,已经加载完成,这时候script.readyState="complete"; 这时候就那些if条件判断时,里面的事件就无法触发,这时里面的函数也无法执行,所以可以先让其进行if条件判断,然后再加载;

[3.6]封装兼容性函数[最终版]:如果只是异步加载脚本库,传入url即可,封装的是较为灵活的,按需加载脚本库、函数,callback如果多个函数,可以以数组形式传入,灵活应用;

补充:

(1).实际操作中又报错;解释:结合预编译的过程,函数执行前并不能解析函数内部到底有什么内容,当函数执行时,执行到第二个参数的时候,里面的脚本库还未加载成功,会报错;

解决方案1:使用函数引用作为参数,当传入时并不会解析里面的内容,用到的时候才会解析;

解决方案2: loadScript("tools.js","test()"); 第二个参数可以为字符串形式,eval();和setInterval();可以将字符串转化为代码执行;不常用,es3.0也不支持eval();

对象属性名的方式也可以;(实操中也可使用)

总结:

(1).渲染引擎解析html/css,js引擎解析javascript代码,domTree + cssTree = renderTree;渲染引擎开始渲染页面;

(2).js会阻塞dom的解析,解析过程就是识别dom元素的过程(domTree包含元素节点/文本节点等系列节点,聚焦点为元素节点),而dom树的加载完成包含里面的图片、a标签的链接等都下载完毕,触发window.onload,显然dom解析必然是在dom加载之前完成;

(3).当属性等于属性值的时候,可直接写一个属性名即可,也称为单属性,系统可以识别,但是最好写成属性=“属性值”的写法;

<script type="text/javascript" src="tools.js" defer="defer"></script>

<script type="text/javascript" src="tools.js" defer></script>


3、js时间线:

(1).创建document对象,开始解析web页面。解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段document.readyState = ‘loading’;

(2).遇到link外部css,创建线程加载,并继续解析文档;

(3).遇到script外部js,并且没有设置async、defer,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档;

(4).遇到script外部js,并且设置有async、defer,浏览器创建线程加载,并继续解析文档。 对于async属性的脚本,脚本加载完成后立即执行;(异步禁止使用document.write())

(5).遇到img等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档;

(6).当文档解析完成,document.readyState = ‘interactive’;

(7).文档解析完成后,所有设置有defer的脚本会按照顺序执行。(注意与async的不同,但同样禁止使用document.write());【defer脚本监视的便是document.readyState的状态】;

(8).document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段;

(9).当所有async的脚本加载完成并执行后、img等加载完成后,document.readyState =‘complete’,window对象触发load事件;

(10).从此,以异步响应方式处理用户输入、网络事件等。

补充:

[1].关于document.write();其会把括号里的内容当作是html文档输出到页面里去,但有两种特殊情况,1.当页面全部加载完成,其会将页面内容全部清空;2.异步加载过程中使用也会将页面内容清空;【开发中也没太大用处,尽量不要使用】

[2].文档解析完成:domTree解析完成,不同于页面加载完成,页面加载完成包括randerTree、js都加载完成;(文档解析完成发生在页面加载完成之前)

[3].事件驱动阶段,页面加载完成后基本都是都是这个阶段,没有事件的为纯静态页面;

[4].window.onload=function(){}; 整个页面加载完成后执行;                                          $(document).ready(function(){ });  jquery中这种方式表示dom解析完就执行;document.addEventListener('DOMContentLoaded',function(){},false);  dom解析完成后就执行;[此事件没有句柄的方式,只能使用addEventListener();]

       如图也不会报错,阻断dom解析进行加载,完成后继续进行dom解析,此事件会在dom解析完成后开始执行,所以这种写法没错,但是不建议;【dom解析目的是生成dom树,script是标签当然也会存在于dom树上,但里面的js代码是js引擎进行解析的,渲染引擎和js引擎功能不同,最后渲染引擎开始渲染页面,就是视图所看到的】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容