Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
當(dāng)我們?cè)L問一個(gè)網(wǎng)站的時(shí)候,我們通常是在瀏覽器中輸入我們所需要訪問的網(wǎng)址,然后點(diǎn)擊就可以瀏覽我們所需要瀏覽的網(wǎng)站,但瀏覽器在我們輸入域名到返回給我們最后的結(jié)果也是經(jīng)歷了一番繁瑣的操作。
瀏覽器通常的步驟如下
1.瀏覽器的地址欄輸入U(xiǎn)RL并按下回車。
2.瀏覽器查找當(dāng)前URL是否存在緩存,并比較緩存是否過期。
3.DNS解析URL對(duì)應(yīng)的IP。
4.根據(jù)IP建立TCP連接(三次握手)。
5.HTTP發(fā)起請(qǐng)求。
6.服務(wù)器處理請(qǐng)求,瀏覽器接收HTTP響應(yīng)。
7.渲染頁面,構(gòu)建DOM樹。
8.關(guān)閉TCP連接(四次揮手)
接下來我們主要分析第七點(diǎn),也就是瀏覽器如何根據(jù)獲取到的文件渲染出相應(yīng)的頁面,主要從HTML、CSS、JS這三點(diǎn)來分析
HTML稱為超文本標(biāo)簽語言,是一種標(biāo)識(shí)性的語言。普通的txt文檔在加了HTML標(biāo)簽之后,就變得具有語義了,瀏覽器能根據(jù)不同的語義進(jìn)行不同的解析。目前常見的HTML分為兩種,一種是HTML另一種是XHTML。相較于XHTML的”嚴(yán)格“,HTML以其相對(duì)較為”寬松“的特效獲得了較為廣泛的喜愛
瀏覽器獲取到HTML文擋的時(shí)候,會(huì)逐行解析文檔,并根據(jù)文檔內(nèi)容將文檔內(nèi)容轉(zhuǎn)化為DOM樹在在瀏覽器中渲染出來
<html> <body> <h1> Hello World </h1> </body> </html> 這是一個(gè)最基礎(chǔ)的HTML文檔,當(dāng)瀏覽器獲取到這個(gè)文件的時(shí)候,通過解析文字中的語義化標(biāo)簽,通過解析標(biāo)簽的<(Tag open state:開始標(biāo)簽)到>(Tag name state:結(jié)束標(biāo)簽),屬性名稱和相應(yīng)值,直到文檔結(jié)束,并將其轉(zhuǎn)換為DOM樹并最終在瀏覽器中繪制出來。
DOM樹
瀏覽器遇到語義解釋性的CSS標(biāo)簽嵌入文件,那么此時(shí)IE的下載過程會(huì)啟用單獨(dú)連接進(jìn)行下載,并在下載后繼續(xù)進(jìn)行解析。并且只有在文件解析完成后才會(huì)在往下解析(瀏覽器阻塞),瀏覽器對(duì)CSS樣式的解析是從左到右的,比如.box .left p,會(huì)在頁面中找到所有的p標(biāo)簽,然后在p標(biāo)簽中找其父元素有.left類的p元素,再找祖父元素有.box的p標(biāo)簽
如下圖示,瀏覽器會(huì)按照從右向左的順序去讀取選擇器。先找到span然后順著往上找到class為“haha”的div再找到id為“molly”的元素。成功匹配到則加入結(jié)果集,如果直到根元素html都沒有匹配,則不再遍歷這條路徑,從下一個(gè)span開始重復(fù)這個(gè)過程
提升渲染效率的幾個(gè)點(diǎn) - 盡量少的去對(duì)標(biāo)簽進(jìn)行選擇,而是用class - 不要去用標(biāo)簽限定ID或者類選擇符 - 減少層級(jí)關(guān)系,使查詢效率更高 - 盡量少的去使用后代選擇器,降低選擇器的權(quán)重值 - 不要放空的class - 多用繼承屬性,可以通過繼承避免對(duì)屬性重復(fù)使用
瀏覽器遇到語義解釋性的JS標(biāo)簽嵌入文件,那么此時(shí)IE的下載過程會(huì)啟用單獨(dú)連接進(jìn)行下載,并在下載后繼續(xù)進(jìn)行解析。并且只有在JS文件解析完成并且加載完后才會(huì)繼續(xù)往下解析(瀏覽器阻塞)
在當(dāng)前作用域中,JavaScript代碼執(zhí)行之前,瀏覽器首先會(huì)默認(rèn)的把所有帶var和function聲明的變量進(jìn)行提前的聲明或者定義(主要指的是ES6之前,由于ES6引了let和const所以會(huì)存在不同)
JS代碼在逐行解析代碼的時(shí)候,變量賦值表達(dá)式是可以修改預(yù)解析的值。但如果有多個(gè)表達(dá)式對(duì)相同的變量多次賦值,那么除過函數(shù)聲明不能修改上次的賦值,變量賦值和函數(shù)表達(dá)式都可以修改這個(gè)變量的值
整個(gè)渲染的過程大致上可以概述為
- 用戶輸入網(wǎng)址,服務(wù)器返回html文檔
- 瀏覽器開始解析HTML文檔
- 瀏覽器解析文檔過程中解析到CSS或者JS標(biāo)簽嵌入文件,這時(shí)候?yàn)g覽器優(yōu)先解析標(biāo)簽嵌入文件,待標(biāo)簽嵌入文件解析完成并執(zhí)行完成后在繼續(xù)解析HTML文檔
- 瀏覽器將解析好的DOM進(jìn)行繪制,在瀏覽器中繪制出來
https://segmentfault.com/a/1190000016253407
https://www.jianshu.com/p/b41f1258c044
覽器輸入U(xiǎn)RL到頁面渲染完成,這個(gè)過程大致可分為兩個(gè)階段:網(wǎng)絡(luò)通信和頁面渲染。
互聯(lián)網(wǎng)內(nèi)各網(wǎng)絡(luò)間設(shè)備的通信遵循TCP/IP協(xié)議,利用TCP/IP協(xié)議進(jìn)行網(wǎng)絡(luò)通信時(shí),會(huì)通過分層與對(duì)方通信。數(shù)據(jù)傳輸?shù)倪^程:由應(yīng)用層產(chǎn)生數(shù)據(jù)后,經(jīng)過傳輸層的分段處理(添加TCP或UDP包頭)、網(wǎng)絡(luò)層(添加IP地址信息)、數(shù)據(jù)鏈路層(封裝成MAC幀)、物理層傳輸電信號(hào)。
??
瀏覽器可以分為兩部分:shell和瀏覽器內(nèi)核,shell是外殼,如工具欄,菜單等,內(nèi)核是根本,是基于標(biāo)記語言顯示的程序或模塊。
瀏覽器內(nèi)核分為兩部分:渲染引擎和JS引擎。
渲染引擎主要負(fù)責(zé)解析瀏覽器所呈現(xiàn)的內(nèi)容,比如HTML,CSS。 渲染引擎的主要流程
始解析 HTML 文檔,并將各標(biāo)記逐個(gè)轉(zhuǎn)化成“內(nèi)容樹”上的 DOM 節(jié)點(diǎn)。同時(shí)也會(huì)解析外部 CSS 文件以及樣式元素中的樣式數(shù)據(jù)。HTML 中這些帶有視覺指令的樣式信息將用于創(chuàng)建另一個(gè)樹結(jié)構(gòu):呈現(xiàn)樹。呈現(xiàn)樹包含多個(gè)帶有視覺屬性(如顏色和尺寸)的矩形。這些矩形的排列順序就是它們將在屏幕上顯示的順序。
呈現(xiàn)樹構(gòu)建完畢之后,進(jìn)入“布局”處理階段,也就是為每個(gè)節(jié)點(diǎn)分配一個(gè)應(yīng)出現(xiàn)在屏幕上的確切坐標(biāo)。下一個(gè)階段是繪制 - 呈現(xiàn)引擎會(huì)遍歷呈現(xiàn)樹,由用戶界面后端層將每個(gè)節(jié)點(diǎn)繪制出來。
需要著重指出的是,這是一個(gè)漸進(jìn)的過程。為達(dá)到更好的用戶體驗(yàn),呈現(xiàn)引擎會(huì)力求盡快將內(nèi)容顯示在屏幕上。它不必等到整個(gè) HTML 文檔解析完畢之后,就會(huì)開始構(gòu)建呈現(xiàn)樹和設(shè)置布局。在不斷接收和處理來自網(wǎng)絡(luò)的其余內(nèi)容的同時(shí),呈現(xiàn)引擎會(huì)將部分內(nèi)容解析并顯示出來。 Webkit 渲染引擎主流程如下圖:
Gecko渲染引擎如下圖:
1、用戶界面。包括地址欄、前進(jìn)/后退按鈕、書簽菜單等。除了瀏覽器主窗口顯示的您請(qǐng)求的頁面外,其他顯示的各個(gè)部分都屬于用戶界面。
2、瀏覽器引擎。在用戶界面和呈現(xiàn)引擎之間傳送指令。
3、呈現(xiàn)引擎。負(fù)責(zé)顯示請(qǐng)求的內(nèi)容。如果請(qǐng)求的內(nèi)容是 HTML,它就負(fù)責(zé)解析 HTML 和 CSS 內(nèi)容,并將解析后的內(nèi)容顯示在屏幕上。
4、用戶界面后端。用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與平臺(tái)無關(guān)的通用接口,而在底層使用操作系統(tǒng)的用戶界面方法。
5、JavaScript 解釋器。用于解析和執(zhí)行 JavaScript 代碼。
6、數(shù)據(jù)存儲(chǔ)。這是持久層。瀏覽器需要在硬盤上保存各種數(shù)據(jù),例如 Cookie。新的 HTML 規(guī)范 (HTML5) 定義了“網(wǎng)絡(luò)數(shù)據(jù)庫”,這是一個(gè)完整(但是輕便)的瀏覽器內(nèi)數(shù)據(jù)庫。
7、網(wǎng)絡(luò)。用于網(wǎng)絡(luò)調(diào)用,比如 HTTP 請(qǐng)求。其接口與平臺(tái)無關(guān),并為所有平臺(tái)提供底層實(shí)現(xiàn)
關(guān)于DOM解析有如下HTML片段
關(guān)于CSS解析
html代碼:
css代碼:
解析成CSS tree
注意:CSS遍歷DOM,一層層找到對(duì)應(yīng)的渲染規(guī)則是十分復(fù)雜的過程,這也是我們經(jīng)常要求盡量精簡DOM結(jié)構(gòu),減少CSS嵌套層級(jí)的原因。CSS渲染流程
1、計(jì)算CSS屬性; 2、構(gòu)建Render Tree; 3、Layout,進(jìn)行定位,元素的坐標(biāo)及尺寸,將元素放到指定位置; 4、繪制注意:圖中有兩種箭頭,一種是指向流程自身的,表示“回流”,即修改某個(gè)屬性會(huì)導(dǎo)致頁面進(jìn)行重新渲染,一種的指向外部的,表示“重繪”,即修改某個(gè)屬性不會(huì)影響整個(gè)頁面布局。
這是前端經(jīng)常會(huì)提到的兩個(gè)概念。 重繪:Repaint,可以理解為頁面局部某個(gè)元素要進(jìn)行重新繪制,比如修改元素的背景顏色,但是幾何尺寸并不會(huì)變; 回流:Reflow,可以理解為頁面整個(gè)重新繪制,比如修改元素的尺寸,往往會(huì)導(dǎo)致整個(gè)render tree要進(jìn)行重新計(jì)算,reflow是從html標(biāo)簽開始自上而下一次重新計(jì)算元素尺寸,重新布局。 通過兩者概念區(qū)別明顯得知,回流要比重繪的成本大得多,我們應(yīng)該盡量減少回流操作,減少頁面性能消耗。
(1)引起回流的方法或操作:
任何會(huì)改變?cè)貛缀涡畔?元素的位置和尺寸大小)的操作,都會(huì)觸發(fā)回流。
(2)常見引起重繪屬性和方法減少reflow/repaint
4.盡可能的修改層級(jí)比較低的DOM。當(dāng)然,改變層級(jí)比較底的DOM有可能會(huì)造成大面積的reflow,但是也可能影響范圍很小。
5.千萬不要使用table布局。因?yàn)榭赡芎苄〉囊粋€(gè)小改動(dòng)會(huì)造成整個(gè)table的重新布局。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。