1照激、json:?輕量級的數(shù)據(jù)交換格式舌仍;[前后端數(shù)據(jù)傳輸都是json格式的恭取,對象里面的鍵必須要有雙引號泰偿,不可省略;傳輸過程中json是以字符串進行傳輸?shù)?直接對象形式傳輸不可以蜈垮,其識別的是二進制耗跛,所以傳輸過程中使用的是二進制的文本格式即字符串]
(1).xml:?其是一種語言(xml ->xhtml ->html),最初也作為數(shù)據(jù)交換格式使用,其以標簽作為數(shù)據(jù)名攒发,標簽內(nèi)容作為數(shù)據(jù)值進行傳遞數(shù)據(jù)课兄,其可以自定義標簽,傳輸效率低下晨继,如今大多使用json;[前后端通信傳遞數(shù)據(jù)是以字符串的形式進行烟阐,字符串內(nèi)填充數(shù)據(jù),而且數(shù)據(jù)就是對象的形式紊扬,前端給后端傳遞數(shù)據(jù)蜒茄,傳遞的是字符串類型的數(shù)據(jù),后臺收到進行解析成對象再進行一系列的操作(類如:表單數(shù)據(jù)收集)餐屎,同理后臺傳遞給前端的數(shù)據(jù)也是字符串格式檀葛,需要轉化為對象] [傳遞數(shù)據(jù)需要高效、便捷]
(2).json 是以對象為樣板腹缩,本質上就是對象屿聋,在js中“一切都是對象”,但其和對象的用途上有區(qū)別藏鹊,對象是本地使用(瀏覽器端润讥、服務器端),json是用來傳輸?shù)呐坦眩问缴弦灿袇^(qū)別楚殿,json中的屬性必須加雙引號,不可省略竿痰;對象中雙引號可以省略【區(qū)分json和對象的要點】
json數(shù)據(jù):var obj = { "name": "abc","age": 18}脆粥;json字符串:"{ "name": "abc","age": 18}"
(3).以下這兩個方法很重要:進行解析數(shù)據(jù)的第一步【JSON、Math都是靜態(tài)類影涉,使用過程中不能new +構造函數(shù)創(chuàng)建對象使用变隔;其上有很多屬性和方法,直接使用就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加載完成孵户,所謂異步加載:工具類/數(shù)據(jù)初始化的js腳本庫異步加載,操作dom元素的js腳本進行同步加載即可岔留;(操作dom元素的js腳本若是異步加載夏哭,每次改動必然會影響domTree,進而影響randerTree,耗費性能); 【js是單線程,若是雙線程献联,一個線程增加dom元素竖配,一個線程刪除dom元素,執(zhí)行哪個里逆?
瀏覽器內(nèi)核中有渲染引擎和js引擎进胯,渲染頁面的過程是怎樣的?html原押、css胁镐、js文件執(zhí)行順序是怎么樣的呢?
頭部引入的css文件和html是異步線程執(zhí)行诸衔,引入的js文件和html是同步執(zhí)行:js文件加載完成后盯漂,html才能接著進行解析,也就是js會阻塞后面的dom解析(若遇到網(wǎng)速不好等情況笨农,整個網(wǎng)站將等待js庫加載而不進行后續(xù)渲染)就缆;日常開發(fā)中,一些工具類的js庫谒亦、引入的第三方庫竭宰,我們希望其可以同時進行加載,沒必要阻塞dom解析份招,影響頁面效率切揭,最好采用異步加載的方式;
(1).接下來先分析一些頁面渲染過程:(結合原生js小結圖示過程)
[1].渲染引擎是一行行(按像素點)進行渲染頁面的锁摔,代碼中就是一行行執(zhí)行代碼(當然并非視覺編程的順序伴箩,有預編譯過程),首先它會進行domTree的繪制鄙漏,遵循“深度優(yōu)先原則”嗤谚,渲染dom的過程中,若是存在一些Img標簽怔蚌、a標簽等含有src巩步、href屬性,和css樣式有所關聯(lián)的桦踊,內(nèi)部依舊會繼續(xù)解析dom元素到domTree上椅野,但css相關樣式也開始繪制;
[2].domTree樹繪制完成后,cssTree的繪制是同時進行的竟闪,[1]中只是繪制相關元素的位置离福,現(xiàn)在開始繪制和domTree有關的所有樣式;
[3].cssTree樹繪制完成后炼蛤,其和domTree會進行結合形成渲染樹妖爷,domTree + cssTree = renderTree;?有了renderTree后,渲染引擎才開始按著它開始渲染頁面理朋;
[4].期間<head></head>標簽部分引入的js文件絮识,其會阻塞頁面的渲染過程,這里還需要介紹兩個重要概念:reflow 嗽上、 repaint次舌;
????????[4.1] js可以操作html,進而也可以間接操作css,每一次操作都會對domTree產(chǎn)生影響兽愤,domTree一變化彼念,就需要重新繪制domTree、cssTree浅萧,這種改變稱為reflow重排(重構国拇、重做),很影響性能惯殊,這也是我們不要隨便修改html結構的原因[常見可引起重構的行為:dom節(jié)點的刪除增加酱吝、dom元素的寬高變化、位置變化土思,display:none -->>> display: block;?改變某個元素會對后續(xù)元素產(chǎn)生一系列影響务热; offsetWidth? offsetHeight 這兩個雖是查看元素,但依舊會對dom元素產(chǎn)生影響]
????????[4.2]repaint?重繪己儒,其區(qū)別于reflow崎岂,只需要進行部分domTree重繪即可,大多是一些樣式的微弱改變闪湾,不影響html結構冲甘,例如字體顏色、背景圖片途样、背景顏色等等江醇,對后續(xù)元素也無影響,對性能也有影響何暇,但很刑找埂;
(2).JS異步加載的三種方法:操作dom元素的還是采取同步加載裆站,對于工具庫/初始化數(shù)據(jù)的庫条辟,采取異步加載或者按需加載來提高頁面效率黔夭;
[1].defer異步加載,只有IE9以下可用羽嫡,在script標簽加入單屬性即可本姥;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?<script type="text/javascript" scr="tools.js" defer="defer"></script>;?其不僅可以引入外部文件,也可以將代碼寫入內(nèi)部杭棵,<script type="text/javascript" defer="defer">console.log('a');<script>; [不要既引入外部婚惫,又在內(nèi)部寫代碼]? 缺點:雖然可以同時進行加載,但必須等到dom文檔全部解析完才會被執(zhí)行颜屠;【注意:IE6和IE7的異步加載最多只能有2個辰妙,當多余兩個的時候必須等前兩個加載完才會加載第三個】
[2].async ,w3c標準,(IE9以下不兼容)鹰祸;<scrip type="text/javascript" src="tools.js" aysnc="aysnc" ></script>;?其只能加載外部腳本甫窟,不能把js代碼寫在內(nèi)部,同時其是加載后就執(zhí)行蛙婴;
如何處理兼容性:封裝在任何瀏覽器都能異步加載腳本庫粗井;
方法一:<script type="text/javascript" aysnc="aysnc" src="tools.js" defer="defer"><script>? ,這種方法不可以街图,容易引起系統(tǒng)崩盤浇衬;
方法二:<script type="text/javascript" aysnc="aysnc" src="tools.js"><script>
<script type="text/javascript" defer="defer" src="tools.js"></script>?這種方式也不合理;
--->>>?開發(fā)中采取的方法:進行if判斷,if(IE){使用defer}else{使用async}
[3].按需加載:異步加載并且按需加載餐济,什么時候用到該腳本耘擂,什么時候進行加載,不用就不用管它絮姆;應用場景也很多醉冤,例如:有的按鈕用戶很少會點擊,但卻有產(chǎn)品價值篙悯,而且點擊有可能會出現(xiàn)很多信息蚁阳,可以對其進行“按需加載”,用戶點擊的時候動態(tài)加載完畢即可鸽照,不一定執(zhí)行到該腳本庫就阻塞頁面或異步加載螺捐;
按需加載才是最合適的異步加載方案:創(chuàng)建script,插入到html中矮燎,加載完畢后callBack;(內(nèi)容較多定血,附詳細過程)
[3.1].?重點:創(chuàng)建script標簽后,添加script.src="tools.js"時诞外,只是進行異步加載糠悼,并沒有執(zhí)行;
-------->>>>>>>代碼跑起來的時候會報錯浅乔,下載資源需要過程:發(fā)出請求倔喂,等待響應铝条,響應后開始反饋資源,期間過程是以微秒(us)計算席噩,由于是異步加載槐秧,下面的代碼在加載過程中便開始執(zhí)行,執(zhí)行過程中若是找不到該方法便會報錯妈候;錯誤原因:加載時間大于代碼執(zhí)行時間综看;
[3.2]使用定時器驗證上述說法:
-------->>>>>代碼可以正常運行,加載的時間受很多因素影響馒索,例如網(wǎng)速不好等莹妒,接下來進行一些操作解決bug,等其加載完成后再執(zhí)行代碼绰上;
[3.3].load事件旨怠,很多對象都有l(wèi)oad事件,并非window獨有(涉及到下載的就有l(wèi)oad事件)蜈块;表示:下載完成后觸發(fā)事件鉴腻,兼容性很好,safari/chrome/firefox/opera都兼容百揭,IE瀏覽器也有l(wèi)oad事件爽哎,但IE中的script標簽上沒有l(wèi)oad事件;
[3.4].IE使用:?readystatechange事件器一,IE在script上設置了狀態(tài)碼readState,隨著加載過程其的屬性值會變化课锌;開始:script.readyState = "loading",--->>>加載完成后:script.readyState="complated" /? script.readyState="loaded";[IE和高版本的chrome、firefox的script有此事件祈秕,但是其他瀏覽器的dom元素上也有此事件和屬性渺贤;document.readyState,表示狀態(tài)]
[3.5]封裝兼容性函數(shù):url:引入的腳步庫踢步,callback();?回調函數(shù)癣亚,當滿足一定條件才執(zhí)行的函數(shù);將script.src=url;換位置的原因是解決bug获印,防止IE無法判斷述雾,解釋:IE判斷的標準就是script的狀態(tài)碼是否發(fā)生變化,若是代碼執(zhí)行到script.src=url;?加載速度特別特別快兼丰,在執(zhí)行下面的判斷語句前玻孟,已經(jīng)加載完成,這時候script.readyState="complete";?這時候就那些if條件判斷時鳍征,里面的事件就無法觸發(fā)黍翎,這時里面的函數(shù)也無法執(zhí)行,所以可以先讓其進行if條件判斷艳丛,然后再加載匣掸;
[3.6]封裝兼容性函數(shù)[最終版]:如果只是異步加載腳本庫趟紊,傳入url即可,封裝的是較為靈活的碰酝,按需加載腳本庫霎匈、函數(shù),callback如果多個函數(shù)送爸,可以以數(shù)組形式傳入铛嘱,靈活應用;
補充:
(1).實際操作中又報錯袭厂;解釋:結合預編譯的過程墨吓,函數(shù)執(zhí)行前并不能解析函數(shù)內(nèi)部到底有什么內(nèi)容,當函數(shù)執(zhí)行時纹磺,執(zhí)行到第二個參數(shù)的時候帖烘,里面的腳本庫還未加載成功,會報錯爽航;
解決方案1:使用函數(shù)引用作為參數(shù)蚓让,當傳入時并不會解析里面的內(nèi)容乾忱,用到的時候才會解析讥珍;
解決方案2: loadScript("tools.js","test()");?第二個參數(shù)可以為字符串形式,eval();和setInterval();可以將字符串轉化為代碼執(zhí)行窄瘟;不常用衷佃,es3.0也不支持eval();
對象屬性名的方式也可以;(實操中也可使用)
總結:
(1).渲染引擎解析html/css,js引擎解析javascript代碼蹄葱,domTree + cssTree = renderTree;渲染引擎開始渲染頁面氏义;
(2).js會阻塞dom的解析,解析過程就是識別dom元素的過程(domTree包含元素節(jié)點/文本節(jié)點等系列節(jié)點图云,聚焦點為元素節(jié)點)惯悠,而dom樹的加載完成包含里面的圖片、a標簽的鏈接等都下載完畢,觸發(fā)window.onload竣况,顯然dom解析必然是在dom加載之前完成克婶;
(3).當屬性等于屬性值的時候,可直接寫一個屬性名即可丹泉,也稱為單屬性情萤,系統(tǒng)可以識別,但是最好寫成屬性=“屬性值”的寫法摹恨;
<script type="text/javascript" src="tools.js" defer="defer"></script>
<script type="text/javascript" src="tools.js" defer></script>
3筋岛、js時間線:
(1).創(chuàng)建document對象,開始解析web頁面晒哄。解析HTML元素和他們的文本內(nèi)容后添加Element對象和Text節(jié)點到文檔中睁宰。這個階段document.readyState = ‘loading’;
(2).遇到link外部css肪获,創(chuàng)建線程加載,并繼續(xù)解析文檔;
(3).遇到script外部js柒傻,并且沒有設置async贪磺、defer,瀏覽器加載诅愚,并阻塞寒锚,等待js加載完成并執(zhí)行該腳本,然后繼續(xù)解析文檔;
(4).遇到script外部js违孝,并且設置有async刹前、defer,瀏覽器創(chuàng)建線程加載雌桑,并繼續(xù)解析文檔喇喉。 對于async屬性的腳本,腳本加載完成后立即執(zhí)行校坑;(異步禁止使用document.write())
(5).遇到img等拣技,先正常解析dom結構,然后瀏覽器異步加載src耍目,并繼續(xù)解析文檔;
(6).當文檔解析完成膏斤,document.readyState = ‘interactive’;
(7).文檔解析完成后,所有設置有defer的腳本會按照順序執(zhí)行邪驮。(注意與async的不同,但同樣禁止使用document.write());【defer腳本監(jiān)視的便是document.readyState的狀態(tài)】;
(8).document對象觸發(fā)DOMContentLoaded事件莫辨,這也標志著程序執(zhí)行從同步腳本執(zhí)行階段,轉化為事件驅動階段;
(9).當所有async的腳本加載完成并執(zhí)行后毅访、img等加載完成后沮榜,document.readyState =‘complete’,window對象觸發(fā)load事件;
(10).從此喻粹,以異步響應方式處理用戶輸入蟆融、網(wǎng)絡事件等。
補充:
[1].關于document.write();其會把括號里的內(nèi)容當作是html文檔輸出到頁面里去守呜,但有兩種特殊情況型酥,1.當頁面全部加載完成,其會將頁面內(nèi)容全部清空弛饭;2.異步加載過程中使用也會將頁面內(nèi)容清空冕末;【開發(fā)中也沒太大用處,盡量不要使用】
[2].文檔解析完成:domTree解析完成侣颂,不同于頁面加載完成档桃,頁面加載完成包括randerTree、js都加載完成憔晒;(文檔解析完成發(fā)生在頁面加載完成之前)
[3].事件驅動階段藻肄,頁面加載完成后基本都是都是這個階段蔑舞,沒有事件的為純靜態(tài)頁面;
[4].window.onload=function(){};?整個頁面加載完成后執(zhí)行嘹屯;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? $(document).ready(function(){ });? jquery中這種方式表示dom解析完就執(zhí)行攻询;document.addEventListener('DOMContentLoaded',function(){},false);? dom解析完成后就執(zhí)行;[此事件沒有句柄的方式州弟,只能使用addEventListener();]
? ? ? ?如圖也不會報錯钧栖,阻斷dom解析進行加載,完成后繼續(xù)進行dom解析婆翔,此事件會在dom解析完成后開始執(zhí)行拯杠,所以這種寫法沒錯,但是不建議啃奴;【dom解析目的是生成dom樹潭陪,script是標簽當然也會存在于dom樹上,但里面的js代碼是js引擎進行解析的最蕾,渲染引擎和js引擎功能不同依溯,最后渲染引擎開始渲染頁面,就是視圖所看到的】