整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢(xún)熱線(xiàn):

          淺談Html的內(nèi)容加載及JS執(zhí)行順序

          事跟我說(shuō)他用jQuery取不到頁(yè)面上隱藏元素input的值,他的html頁(yè)面大概內(nèi)容如下。

          <!DOCTYPE html>
          <html lang="zh">
           
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          	<script type="text/javascript" src="jslib/jquery-1.11.2.min.js"></script>
          	<title>淺談Html頁(yè)面內(nèi)容執(zhí)行順序</title>
          	<script type="text/javascript">
          		var userId = $('#hiddenUserId').val();
          		var contextPath = $('#hiddenContextPath').val();
          		var userName = $('#hiddenUserName').val();
          	</script>
          </head>
           
          <body>
          	<input type="hidden" id="hiddenUserId" value="101" />
          	<input type="hidden" id="hiddenContextPath" value="/web" />
          	<input type="hidden" id="hiddenUserName" value="小明" />
          </body>
           
          </html>

          頁(yè)面中的JS腳本在head中,JS腳本要讀取的input在body中。瀏覽器對(duì)html頁(yè)面內(nèi)容的加載是順序加載,也就是在html頁(yè)面中前面先加載,因此當(dāng)加載到JS腳本時(shí),input還沒(méi)有加載到瀏覽器中。JS是一種解釋性的腳本,也是從上而下順序執(zhí)行,由于這段JS代碼是立即執(zhí)行的,所以當(dāng)JS在執(zhí)行的時(shí)候,讀取不到input的值。

          最直接的修改方法是把JS放到網(wǎng)頁(yè)的最下面執(zhí)行。

          <!DOCTYPE html>
          <html lang="zh">
           
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          	<script type="text/javascript" src="jslib/jquery-1.11.2.min.js"></script>
          	<title>淺談Html頁(yè)面內(nèi)容執(zhí)行順序</title>	
          </head>
           
          <body>
          	<input type="hidden" id="hiddenUserId" value="101" />
          	<input type="hidden" id="hiddenContextPath" value="/web" />
          	<input type="hidden" id="hiddenUserName" value="小明" />
          	
          	<script type="text/javascript">
          		var userId = $('#hiddenUserId').val();
          		var contextPath = $('#hiddenContextPath').val();
          		var userName = $('#hiddenUserName').val();
          	</script>
          </body>
           
          </html>

          把JS放到網(wǎng)頁(yè)的最下面,這樣在JS執(zhí)行的時(shí)候,網(wǎng)頁(yè)內(nèi)容都已經(jīng)加載完畢。把JS放在網(wǎng)頁(yè)的最下面方法并不是最好的解決方法,大部分情況JS并不是總能放在網(wǎng)頁(yè)的最下面。這時(shí)可以用window的onload事件,onload事件在整個(gè)頁(yè)面都加載完成后才觸發(fā),可以把JS腳本放在onload里面執(zhí)行。不同瀏覽器onload事件添加方式也不一樣。

          IE下事件:

          window.attachEvent('onload', function(){
          			var userId = $('#hiddenUserId').val();
          			var contextPath = $('#hiddenContextPath').val();
          			var userName = $('#hiddenUserName').val();
          		});

          Chrome/Firefox等DOM標(biāo)準(zhǔn)事件:

          window.addEventListener('load', function(){
          			var userId = $('#hiddenUserId').val();
          			var contextPath = $('#hiddenContextPath').val();
          			var userName = $('#hiddenUserName').val();
          		});

          由于不同瀏覽器的事件添加方式不一樣,jQuery為我們提供了通用的初始化方法,該方法在頁(yè)面加載完成時(shí)觸發(fā)。

          $(function(){
          			var userId = $('#hiddenUserId').val();
          			var contextPath = $('#hiddenContextPath').val();
          			var userName = $('#hiddenUserName').val();
          		});

          上面方法本質(zhì)就是添加onload監(jiān)聽(tīng)事件。

          最終修改后的頁(yè)面

          SS加載存在先后順序,不嚴(yán)謹(jǐn)?shù)臅?shū)寫(xiě)順序?qū)?huì)導(dǎo)致界面出現(xiàn)偏差。并且正確的書(shū)寫(xiě)順序也可以提高代碼的可讀性。

          正確的排序方式如下:

          (1)定位屬性:position display float left top right bottom overflow clear z-index flex

          (2)自身屬性:width height padding border margin background

          (3)文字屬性:font-famliy font-size font-style font-weight font-varient color

          (4)文本屬性:text-align vertical-align text-wrap text-transform text-indent text-ecoration letter-spacing white-spacing white-space text-overflow

          (5)CSS3中新增屬性:content box-shadow border-radius transform……

          css順序按照以上順序書(shū)寫(xiě)即可。

          <h4 id="目的減少瀏覽器的reflow回流提高瀏覽器加載速度">目的:減少瀏覽器的reflow(回流),提高瀏覽器加載速度

          接下來(lái)講解瀏覽器的渲染原理

          瀏覽器引擎簡(jiǎn)介

          瀏覽器——Firefox、Chrome和Safari是基于兩種渲染引擎構(gòu)建的,F(xiàn)irefox使用Geoko——Mozilla自主研發(fā)的渲染引擎,Safari和Chrome都使用webkit。

          渲染主流程

          渲染引擎首先通過(guò)網(wǎng)絡(luò)獲得所請(qǐng)求文檔的內(nèi)容,通常以8K分塊的方式完成。下面是渲染引擎在取得內(nèi)容之后的基本流程:

          ①解析html以構(gòu)建dom樹(shù) -> ②構(gòu)建render樹(shù) -> ③布局render樹(shù) -> ④繪制render樹(shù)

          css樣式解析到顯示至瀏覽器屏幕上就發(fā)生在②③④步驟,可見(jiàn)瀏覽器并不是一獲取到css樣式就立馬開(kāi)始解析而是根據(jù)css樣式的書(shū)寫(xiě)順序?qū)⒅凑誨om樹(shù)的結(jié)構(gòu)分布render樣式,完成第②步,然后開(kāi)始遍歷每個(gè)樹(shù)結(jié)點(diǎn)的css樣式進(jìn)行解析,此時(shí)的css樣式的遍歷順序完全是按照之前的書(shū)寫(xiě)順序。在解析過(guò)程中,一旦瀏覽器發(fā)現(xiàn)某個(gè)元素的定位變化影響布局,則需要倒回去重新渲染。

          概念:

          DOM Tree:瀏覽器將HTML解析成樹(shù)形的數(shù)據(jù)結(jié)構(gòu)。

          CSS Rule Tree:瀏覽器將CSS解析成樹(shù)形的數(shù)據(jù)結(jié)構(gòu)。

          Render Tree: DOM和CSSOM合并后生成Render Tree。

          layout: 有了Render Tree,瀏覽器已經(jīng)能知道網(wǎng)頁(yè)中有哪些節(jié)點(diǎn)、各個(gè)節(jié)點(diǎn)的CSS定義以及他們的從屬關(guān)系,從而去計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕中的位置。

          painting: 按照算出來(lái)的規(guī)則,通過(guò)顯卡,把內(nèi)容畫(huà)到屏幕上。

          reflow(回流):當(dāng)瀏覽器發(fā)現(xiàn)某個(gè)部分發(fā)生了點(diǎn)變化影響了布局,需要倒回去重新渲染,內(nèi)行稱(chēng)這個(gè)回退的過(guò)程叫reflow。reflow會(huì)從 (html)根節(jié)點(diǎn) 這個(gè)root frame開(kāi)始遞歸往下,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置。reflow幾乎是無(wú)法避免的。

          repaint(重繪):改變某個(gè)元素的背景色、文字顏色、邊框顏色等等不影響它周?chē)騼?nèi)部布局的屬性時(shí),屏幕的一部分要重畫(huà),但是元素的幾何尺寸沒(méi)有變。

          例如:現(xiàn)在界面上流行的一些效果,比如樹(shù)狀目錄的折疊、展開(kāi)(實(shí)質(zhì)上是元素的顯 示與隱藏)等,都將引起瀏覽器的 reflow。鼠標(biāo)滑過(guò)、點(diǎn)擊……只要這些行為引起了頁(yè)面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會(huì)引起它內(nèi)部、周?chē)踔琳麄€(gè)頁(yè)面的重新渲染。

          注意:

          (1)display:none 的節(jié)點(diǎn)不會(huì)被加入Render Tree,而visibility: hidden 則會(huì),所以,如果某個(gè)節(jié)點(diǎn)最開(kāi)始是不顯示的,設(shè)為display:none是更優(yōu)的。

          (2)display:none 會(huì)觸發(fā) reflow,而 visibility:hidden 只會(huì)觸發(fā) repaint,因?yàn)闆](méi)有發(fā)現(xiàn)位置變化。

          (3)有些情況下,比如修改了元素的樣式,瀏覽器并不會(huì)立刻reflow 或 repaint 一次,而是會(huì)把這樣的操作積攢一批,然后做一次 reflow,這又叫異步 reflow 或增量異步 reflow。但是在有些情況下,比如resize 窗口,改變了頁(yè)面默認(rèn)的字體等。對(duì)于這些操作,瀏覽器會(huì)馬上進(jìn)行 reflow。

          覽器的工作機(jī)制,一句話(huà)概括起來(lái)就是:web瀏覽器與web服務(wù)器之間通過(guò)HTTP協(xié)議進(jìn)行通信的過(guò)程。所以,C/S之間握手的協(xié)議就是HTTP協(xié)議。瀏覽器接收完畢開(kāi)始渲染之前大致過(guò)程如下:

          從瀏覽器地址欄的請(qǐng)求鏈接開(kāi)始,瀏覽器通過(guò)DNS解析查到域名映射的IP地址,成功之后瀏覽器端向此IP地址取得連接,成功連接之后,瀏覽器端將請(qǐng) 求頭信息 通過(guò)HTTP協(xié)議向此IP地址所在服務(wù)器發(fā)起請(qǐng)求,服務(wù)器接受到請(qǐng)求之后等待處理,最后向?yàn)g覽器端發(fā)回響應(yīng),此時(shí)在HTTP協(xié)議下,瀏覽器從服務(wù)器接收到 text/html類(lèi)型的代碼,瀏覽器開(kāi)始顯示此html,并獲取其中內(nèi)嵌資源地址,然后瀏覽器再發(fā)起請(qǐng)求來(lái)獲取這些資源,并在瀏覽器的html中顯示。

          離我們最近并能直接顯示一個(gè)完整通信過(guò)程的工具就是Firebug了,看下圖:

          其中黃色的tips浮層告訴了我們”colorBox.html”從發(fā)起請(qǐng)求到關(guān)閉連接整個(gè)過(guò)程中每個(gè)環(huán)節(jié)的時(shí)長(zhǎng)(域名解析 -> 建立連接 -> 發(fā)起請(qǐng)求 -> 等待響應(yīng) -> 接收數(shù)據(jù)),點(diǎn)擊該請(qǐng)求,可以獲得HTTP的headers信息,包含響應(yīng)頭信息與請(qǐng)求頭信息,如:

          //響應(yīng)頭信息 HTTP/1.1 304

          Server: Apache/2.2.4 (Win32) PHP/5.2.1 Connection: Keep-Alive Keep-Alive: timeout=5, max=100 Etag: "1e483-1324-a86f5621"

          //請(qǐng)求頭信息 GET /Docs/eva/api/colorBox.html HTTP/1.1 Host: ued.com User-Agent: Mozilla/5.0

          Firefox/3.6.13 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,zh;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Connection: keep-alive Referer: http://ued.com/Docs/ If-Modified-Since: Thu, 17 Feb 2011 10:14:07 GMT If-None-Match: "1e483-1324-a86f5621" Cache-Control: max-age=0

          另外,ajax異步請(qǐng)求同樣遵循HTTP協(xié)議,原理大同小異。

          瀏覽器加載顯示html頁(yè)面內(nèi)容的順序

          我們經(jīng)常看到瀏覽器在加載某個(gè)頁(yè)面時(shí),部分內(nèi)容先顯示出來(lái),又有些內(nèi)容后顯示。那么瀏覽器加載顯示html究竟是按什么順序進(jìn)行的呢?

          其實(shí)瀏覽器加載顯示html的順序是按下面的順序進(jìn)行的:

          1、IE下載的順序是從上到下,渲染的順序也是從上到下,下載和渲染是同時(shí)進(jìn)行的。

          2、在渲染到頁(yè)面的某一部分時(shí),其上面的所有部分都已經(jīng)下載完成(并不是說(shuō)所有相關(guān)聯(lián)的元素都已經(jīng)下載完)。

          3、如果遇到語(yǔ)義解釋性的標(biāo)簽嵌入文件(JS腳本,CSS 劍 敲創(chuàng)聳盜E的下載過(guò)程會(huì)啟用單獨(dú)連接進(jìn)行下載。

          4、并且在下載后進(jìn)行解析,解析過(guò)程中,停止頁(yè)面所有往下元素的下載。

          5、樣式表在下載完成后,將和以前下載的所有樣式表一起進(jìn)行解析,解析完成后,將對(duì)此前所有元素(含以前已經(jīng)渲染的)重新進(jìn)行渲染。

          6、JS、CSS中如有重定義,后定義函數(shù)將覆蓋前定義函數(shù)。

          Firefox處理下載和渲染順序大體相同,只是在細(xì)微之處有些差別,例如:iframe的渲染

          如果你的網(wǎng)頁(yè)比較大,希望部分內(nèi)容先顯示出來(lái),粘住瀏覽者,那么你可以按照上面的規(guī)則合理的布局你的網(wǎng)頁(yè),達(dá)到預(yù)期的目的。

          JS的加載

          不能并行下載和解析(阻塞下載)

          當(dāng) 引用了JS的時(shí)候,瀏覽器發(fā)送1個(gè)jsrequest就會(huì)一直等待該request的返回。因?yàn)闉g覽器需要1個(gè)穩(wěn)定的DOM樹(shù)結(jié)構(gòu),而JS中很有可能有代 碼直接改變了DOM樹(shù)結(jié)構(gòu),比如使用 document.write 或 appendChild,甚至是直接使用的location.href進(jìn)行跳轉(zhuǎn),瀏覽器為了防止出現(xiàn)JS修改DOM樹(shù),需要重新構(gòu)建DOM樹(shù)的情況,所以 就會(huì)阻塞其他的下載和呈現(xiàn).

          為了更清楚的顯示頁(yè)面元素的加載順序,動(dòng)手寫(xiě)了一個(gè)程序,程序?qū)?yè)面中的每個(gè)元素都延遲10秒。

          程序的位置在見(jiàn)附件。

          首先查看TestHtmlOrder.aspx這個(gè)頁(yè)面,使用HttpWatcher來(lái)檢測(cè)頁(yè)面元素的加載。

          從下面的圖中可以看到加載順序。

          IE首先加載了主頁(yè)面TestHtmlOrder.aspx,

          下載了主頁(yè)面后,頁(yè)面首先顯示的是“紅色劍靈”、“藍(lán)色劍靈”幾個(gè)字,但此時(shí)顯示的是只是黑色字體,沒(méi)有樣式,因?yàn)闃邮竭€沒(méi)有下載下來(lái)。

          接下來(lái)頁(yè)面中的標(biāo)簽是JS標(biāo)簽,屬于嵌入文件,因此IE需要將其下載下來(lái)。這有兩個(gè)文件,雖然IE同時(shí)能夠和WebServer建立兩個(gè)鏈接,但是此時(shí)并沒(méi)有使用兩個(gè)連接,而是使用一個(gè)連接,在下載完成后,接下來(lái)才下載另外一個(gè)文件。

          究其原因,是因?yàn)镴S包含了語(yǔ)法定義,在第二個(gè)文件里面的函數(shù)可能用到了第一個(gè)文件里面的變量和函數(shù),IE沒(méi)有辦法判斷,或者需要很耗時(shí)的判斷,才 能判斷文件下載的先后順序。而在解釋方面,IE對(duì)JS文件是下載一個(gè),解釋一個(gè)(可以執(zhí)行文件TestJsOrder2.aspx)。如果先下載的是第二 個(gè)文件,此時(shí)就會(huì)發(fā)生解釋錯(cuò)誤。因此需要開(kāi)發(fā)者自己在放置JS文件位置時(shí),按先后順序放好,IE依次下載進(jìn)行解釋。后面的函數(shù)覆蓋前面的函數(shù)定義

          在下載完成后,我們看到helloWorld,helloworld2,開(kāi)始順序執(zhí)行。而此時(shí)字體的樣式表和圖片仍然沒(méi)有下載下來(lái)。

          在helloWorld,helloWorld2執(zhí)行過(guò)程時(shí),此時(shí)頁(yè)面停留在函數(shù)執(zhí)行的中斷點(diǎn)(alert部分)。此時(shí)IE并沒(méi)有去下載CSS的文件。由此說(shuō)明JS函數(shù)的執(zhí)行會(huì)阻塞IE的下載。

          接下來(lái)我們看到CSS文件的下載也是使用了一個(gè)連接,也是串行下載。其串行下載的原因和JS串行下載原因是一樣的。

          在兩個(gè)CSS文件下載過(guò)程中,我們看到“紅色劍靈”,“藍(lán)色劍靈”依次變?yōu)榧t色和藍(lán)色,兩者顏色的轉(zhuǎn)換時(shí)間相差在10秒,說(shuō)明樣式文件和JS文件一樣是下載完一個(gè)解析一個(gè)的。

          現(xiàn)在轉(zhuǎn)到TestCssOrder.aspx看一下,可以看到 開(kāi)始時(shí)“紅色劍靈”,“紅色強(qiáng)壯劍靈”,顯示為紅色,過(guò)了10秒“藍(lán)色劍靈”顯示為藍(lán)色,再過(guò)10秒,“紅色強(qiáng)壯劍靈”字體變粗了,同時(shí)“紅色強(qiáng)壯劍靈 2”開(kāi)始出現(xiàn)。在剛開(kāi)始“紅色劍靈”,“紅色強(qiáng)壯劍靈”顯示紅色時(shí),第三個(gè)樣式還沒(méi)有下載下來(lái),此時(shí)IE使用已經(jīng)下載到樣式對(duì)上面的元素渲染了一遍,此時(shí) 雖然“紅色劍靈”,“紅色強(qiáng)壯劍靈”樣式定義不同,但是顯示效果一樣。第三個(gè)文件下載后,此時(shí)IE又重新對(duì)“紅色強(qiáng)壯劍靈”渲染了一遍,此時(shí)其變?yōu)榧哟郑?以上所有的文件加載并且渲染完成后,開(kāi)始渲染下面的標(biāo)簽“紅色強(qiáng)壯劍靈2”

          有一點(diǎn)需要證明:在IE使用樣式對(duì)標(biāo)簽進(jìn)行渲染時(shí),是不是停止了其他頁(yè)面元素的下載?原來(lái)我想通過(guò)加長(zhǎng)渲染時(shí)間(利用濾鏡,將標(biāo)簽元素?cái)?shù)目增大)來(lái)檢測(cè),不過(guò)沒(méi)有驗(yàn)證成功。只是從JS函數(shù)的執(zhí)行推斷CSS的渲染也是如此。

          接下來(lái)看到的是圖片文件下載,此時(shí)看到的是兩個(gè)圖片同時(shí)開(kāi)始下載,而且是下載完成后,立即在頁(yè)面上開(kāi)始顯示,直到所有的圖片下載完成。

          注:一個(gè)測(cè)試文件在網(wǎng)絡(luò)傳輸上所花費(fèi)時(shí)間的辦法。

          首先需要明白檢測(cè)中w ait值的意義:wait = 服務(wù)器所花時(shí)間 + 網(wǎng)絡(luò)時(shí)間

          服務(wù)器所花時(shí)間我們可以用Thread.Sleep(10000);來(lái)讓其休息10s,

          比如這個(gè):

          由此大概可以計(jì)算出 10.002-10 = 0.002秒,這就是大概在網(wǎng)絡(luò)上所花的時(shí)間。


          主站蜘蛛池模板: 国产一区二区三区免费观在线| 亚洲一区二区久久| 国产精品久久一区二区三区| 91午夜精品亚洲一区二区三区| 91视频一区二区| 加勒比无码一区二区三区| 天美传媒一区二区三区| 夜夜精品无码一区二区三区| 日韩人妻无码一区二区三区| 亚洲av无码一区二区三区乱子伦| 国产区精品一区二区不卡中文| 久久精品道一区二区三区| 亚洲一区二区久久| 日本高清无卡码一区二区久久| 国产亚洲一区二区三区在线观看 | 国产精品成人一区二区| 风间由美性色一区二区三区| 日本高清一区二区三区| 久久一区二区三区99| 91视频国产一区| 亚洲色婷婷一区二区三区| 国模无码视频一区| 亚洲视频在线观看一区| 亚洲国产精品一区二区第四页| 久久久久人妻一区精品色| 色一乱一伦一区一直爽| 亚洲变态另类一区二区三区| 久久精品国产第一区二区| 亚洲av永久无码一区二区三区| 国产一区二区不卡在线播放| 国产一区中文字幕在线观看| 影音先锋中文无码一区| 国产一区二区在线视频| 国产成人久久精品麻豆一区| 国产在线视频一区二区三区| 精品国产一区二区三区香蕉事| 精品人妻少妇一区二区三区不卡 | 99久久精品日本一区二区免费| 无码乱人伦一区二区亚洲一| 中文字幕不卡一区| 亚洲一区无码精品色|