瀏覽器的渲染原理

1.網(wǎng)頁的解析過程

2. 瀏覽器渲染流程

3.回流和重繪解析

4.合成和性能優(yōu)化

5.defer和async屬性


1.網(wǎng)頁的解析過程

image.png

輸入網(wǎng)址,DNS解析眷茁,返回ip(服務(wù)器地址)芬首,一般情況下谈况,服務(wù)器會給我們返回一個index.html的網(wǎng)頁涉瘾。
瀏覽器解析html頁面要出,如果遇到css的話捉偏,會去服務(wù)器下載css文件倒得;遇到script標(biāo)簽的話,會加載和執(zhí)行對應(yīng)的js代碼夭禽;
把這些東西都下載下來之后霞掺,接下來瀏覽器的內(nèi)核和js引擎會對css讹躯,js菩彬,html進行相關(guān)的操作;
然后潮梯,一個網(wǎng)頁下載下來后骗灶,就是由我們的渲染引擎來幫助我們解析的。

1.1 瀏覽器內(nèi)核和js引擎

1.1.1 瀏覽器內(nèi)核

Rendering Engine秉馏,排版引擎耙旦,頁面渲染引擎。一般習(xí)慣將之稱為“瀏覽器內(nèi)核”萝究,主要功能是解析HTML/CSS進行渲染頁面免都,渲染引擎決定了瀏覽器如何顯示網(wǎng)頁的內(nèi)容以及頁面的格式信息。
1帆竹、 IE瀏覽器內(nèi)核:Trident內(nèi)核绕娘,也是俗稱的IE內(nèi)核;
2栽连、Chrome瀏覽器內(nèi)核:Blink內(nèi)核险领;
3侨舆、Firefox瀏覽器內(nèi)核:Gecko內(nèi)核,俗稱Firefox內(nèi)核绢陌;
4挨下、Safari瀏覽器內(nèi)核:Webkit內(nèi)核;

1.1.2 js引擎

js引擎是解析下面,執(zhí)行js代碼复颈。
chrom,node:v8
webkit:JavaScriptCore

2. 渲染引擎如何解析頁面

2.PNG

1.HTML解析過程

image.png

先下載index.html沥割,所有的解析過程都是通過index.html開始的耗啦。
瀏覽器內(nèi)核里面有個HTML Parser;它通過Parser將html轉(zhuǎn)換成dom樹机杜,

2.生成css規(guī)則

image.png

css也會被css Parser進行解析帜讲,解析成css規(guī)則(display:xxx;color:xxx);
首先椒拗,如果是head里面寫的style樣式似将,那么就不用下載了,就直接一個單獨的線程幫助我們解析css蚀苛,生成css規(guī)則
遇到link的時候在验,瀏覽器會使用一個獨立的線程下載對應(yīng)的css文件,(下載css也不會影響dom解析)把
css文件下載下來之后堵未,也會有一個單獨的線程會幫助我們解析css規(guī)則腋舌。下載css是不會阻塞dom解析的,你html Parser該生成dom樹生成dom樹渗蟹,繼續(xù)解析html块饺。
但是需要注意的是如果html parser已經(jīng)解析完html,生成好了dom tree雌芽,但是這個時候css parser并沒有生成好style rules(規(guī)則樹 css om /css object model)授艰,那么這個時候沒辦法生成render tree。webkit的話世落,這個時候html parser會等到sytle rules生成淮腾,等兩個都有的時候,我在生成render tree屉佳。
總結(jié)就是解析css并不影響dom tree的生成来破,但是影響render tree的生成。

3.構(gòu)建Render Tree

image.png

就是css規(guī)則(cssom)和dom樹結(jié)合到一起變成attachment忘古,然后就生成了render tree渲染樹;

5.布局和繪制

image.png
  • render tree只是告訴我們要顯示什么節(jié)點诅诱,節(jié)點里面有什么樣式髓堪,但是不會有節(jié)點的位置,大小信息,尺寸之類的干旁。
    布局就是確認render tree上面的所有節(jié)點的寬度驶沼,高度和位置信息。
    有了layout之后争群,我們可以確認每個節(jié)點的里面的樣式回怜,里面的內(nèi)容位置信息,大小信息换薄。
  • 一旦有了布局layout玉雾,我們就可以繪制了paint。
    paint就是將每個box盒子轉(zhuǎn)換成屏幕上實際的像素點轻要。
    包括文本复旬,顏色,邊框冲泥,陰影驹碍,替換元素等。

3.回流和重繪

3.1回流(重排)

1.理解回流reflow

  1. 第一次確定節(jié)點的大小和位置凡恍,稱之為布局(layout)志秃。
  2. 之后對節(jié)點的大小、位置修改重新計算稱之為回流嚼酝。

2.什么情況下引起回流呢

1. 比如DOM結(jié)構(gòu)發(fā)生改變(添加新的節(jié)點或者移除節(jié)點)浮还;
添加新節(jié)點或者移除節(jié)點,其他dom的位置也會發(fā)生變化
--> domtree發(fā)生了變化革半,所以render tree一定會變化碑定,render tree變化了,就要重新計算layout又官,就是每個節(jié)點的尺寸延刘,大小,在瀏覽器的位置都得重新計算六敬。重新計算之后就得重新繪制碘赖,painting,就是轉(zhuǎn)換為實際的像素點顯示在屏幕上外构。

  1. 比如改變了布局(修改了width普泡、height、padding审编、font-size等值)
    改變字體大小改變布局是因為span元素是由文字大小撐起來的撼班,字體變大,span這個盒子變大垒酬,就得重新繪制砰嘁。
    boxEl.style.height="200px"
    修改某個節(jié)點的高度的話件炉,dom 樹沒有發(fā)生改變,render樹沒有發(fā)生改變矮湘,但是節(jié)點的大小改變了斟冕,就需要重新進行l(wèi)ayout計算,重繪缅阳。
    改變文字顏色的話磕蛇,是不需要做重新布局的,因為節(jié)點的內(nèi)容十办,大小秀撇,在瀏覽器的位置都沒有改變,不需要重新布局橘洞。
    如果修改了某個東西之后捌袜,你得再次計算這些元素的布局(node 的節(jié)點大小,位置信息)炸枣,不論一個節(jié)點還是多個節(jié)點虏等,有些時候你改了一個,影響其他的節(jié)點适肠,這個時候也得重新layout霍衫。
    如果一個元素是絕對定位,脫離了標(biāo)準(zhǔn)流侯养,改變它對其他節(jié)點沒影響敦跌,但是它本身大小發(fā)生變化,也會重新layout逛揩。
    總結(jié)就是對節(jié)點的大小柠傍,位置修改重新計算的,就叫做回流

  2. 比如窗口resize(修改了窗口的尺寸等)
    比如flex布局辩稽,窗口縮小之后惧笛,一行放不下,就放到第二行逞泄,float布局也是患整。

  3. 比如調(diào)用getComputedStyle方法獲取尺寸、位置信息喷众;這個取決于瀏覽器各谚。
    獲取顏色信息不會,但是獲取尺寸的話到千,就會重新construct frames構(gòu)建frame昌渤,就會重新layout


    image.png

3.2 重繪repaint

1.理解重繪

  1. 第一次渲染內(nèi)容稱之為繪制(paint)。
  2. 之后重新渲染稱之為重繪憔四。

2.什么情況下引起重繪呢

比如修改背景色愈涩、文字顏色望抽、邊框顏色、樣式(實線變成虛線)等履婉;
但是如果改變border-width,就會回流斟览,重新layout毁腿,因為節(jié)點大小改變,boder-style,bordr-color就只是引起重繪苛茂。

3.3回流和重繪之間的關(guān)系

  1. 回流一定會引起重繪已烤,所以回流是一件很消耗性能的事情。
  2. 所以在開發(fā)中要盡量避免發(fā)生回流:

3.4 如何盡量避免發(fā)生回流

? 1.修改樣式時盡量一次性修改
比如通過cssText修改妓羊,比如通過添加class修改
比如這個樣子
box.style.width="200px"
box.style.height="200px"
這個樣子會引起2次回流胯究,不過放在同一個腳本里面的話拧抖,瀏覽器會最后房子一起只進行一次重繪庐完。但是依賴于瀏覽器贞间,所以我們還是避免進行這個樣子的操作村象。樣式盡量一次性修改完成腐碱。比如cssText進行修改笋鄙,或者動態(tài)地添加class掠拳,在class里面把css寫好冒掌。

? 2.盡量避免頻繁的操作DOM
我們可以在一個DocumentFragment或者父元素中淹父,將要操作的DOM操作完成株婴,再一次性的操作;
把操作放到父元素里面暑认,操作完成之后困介,最后再添加到dom里面。
這也是虛擬dom提高性能的原因蘸际。
? 3.盡量避免通過getComputedStyle獲取尺寸座哩、位置等信息;
? 4.對某些元素使用position的absolute或者fixed
并不是不會引起回流捡鱼,而是開銷相對較小八回,不會對其他元素造成影響。 改變absolute或者fixed的大小之后驾诈,指會對自己的大小進行重新計算缠诅,重新layout,其他節(jié)點不需要重新計算乍迄,整體來說計算量相對小一些管引。

4.合成和性能優(yōu)化

4.1 特殊解析-composite合成

  1. 繪制的過程,可以將布局后的元素會知道多個合成圖層中闯两。這是瀏覽器的一種優(yōu)化手段褥伴。

  2. 默認情況下谅将,標(biāo)準(zhǔn)流中的內(nèi)容都是被繪制在同一個圖層layer中的。
    如果當(dāng)前元素是在標(biāo)準(zhǔn)流里面的重慢,經(jīng)過各自解析饥臂,變成render tree,經(jīng)過layout似踱,生成了一種樹結(jié)構(gòu)隅熙,也就是layout tree。 如果這些元素都是標(biāo)準(zhǔn)流里面的核芽,那么會生成render layer囚戚,渲染圖層。
    如果有個元素position:absolute轧简,他會生成另外一個render layer驰坊。
    然后它會將我們多個render layer做一個合成。

  3. 而一些特殊的屬性哮独,會創(chuàng)建一個新的合成層( CompositingLayer )拳芙,并且新的圖層可以利用GPU來加速繪制;
    除了標(biāo)準(zhǔn)流和固定定位之類的會被分別創(chuàng)建圖層,然后放到一個合成層里面借嗽, 一些特殊的元素态鳖,也會創(chuàng)建一個新的合成層,compositing layer恶导。
    因為新的合成層的每一個單獨的合成層都是單獨渲染的浆竭,都是可以利用GPU來加速繪制的。
    就是如果生成一份單獨的合成層惨寿,原來的哪些合成詞就不需要動邦泄,只需要單獨改這一個合成層,并且進行渲染裂垦。

4.2 那么哪些屬性可以形成新的合成層呢

  • 3D transforms
  • video顺囊、canvas、iframe
  • opacity 動畫轉(zhuǎn)換時蕉拢;
  • position: fixed(absolute是普通的圖層特碳,不會生成 新的圖層)
  • will-change:一個實驗性的屬性,提前告訴瀏覽器元素可能發(fā)生哪些變化晕换;
  • animation 或 transition 設(shè)置了opacity午乓、transform;
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #test,
      #container {
        height: 100px;
        width: 100px;
        background-color: yellow;
      }
      #container {
        background-color: red;
        /*   position: fixed;  新的圖層*/
        /*  transform: translateZ(0);新的圖層*/
        transition: transform 1s ease;
        /* 利用transform去執(zhí)行動畫的時候闸准,對瀏覽器來說性能會更高益愈,因為他是在獨立 的圖層里面給你做動畫,*/
      }
      #container:hover {
        transform: translateX(100px); /* 不會引起回流 */
        /* margin-left:100px這樣的話就是在默認圖層里面,效率很低 蒸其,而且會引起回流*/
      }
    </style>
  </head>
  <body>
    <div id="test">test</div>
    <div id="container"></div>
  </body>
</html>

4.3 缺點

分層確實可以提高性能敏释,但是它以內(nèi)存管理為代價,因此不應(yīng)作為 web 性能優(yōu)化策略的一部分過度使用摸袁。

5.defer和async屬性

5.1 script元素和頁面解析的關(guān)系

1. js加載執(zhí)行過程

  • 瀏覽器在解析HTML的過程中钥顽,遇到了script元素是不能繼續(xù)構(gòu)DOM樹的;
  • 它會停止繼續(xù)構(gòu)建但惶,首先下載JavaScript代碼耳鸯,并且執(zhí)行JavaScript的腳本;
  • 只有等到JavaScript腳本執(zhí)行結(jié)束后膀曾,才會繼續(xù)解析HTML,構(gòu)建DOM樹阳啥;

2. 原因

  • 這是因為JavaScript的作用之一就是操作DOM添谊,并且可以修改DOM;js代碼可以直接對dom樹進行操作


    image.png

    紫色三角形里面指的是js代碼對dom進行操作察迟。

  • 如果我們等到DOM樹構(gòu)建完成并且渲染再執(zhí)行JavaScript斩狱,修改dom, 會造成嚴(yán)重的回流和重繪扎瓶,影響頁面的性能所踊;
  • 所以會在遇到script元素時,優(yōu)先下載和執(zhí)行JavaScript代碼概荷,再繼續(xù)構(gòu)建DOM樹秕岛;

3.問題

  • 在目前的開發(fā)模式中(比如Vue、React)误证,腳本往往比HTML頁面更“重”继薛,處理時間需要更長;
  • 所以會造成頁面的解析阻塞愈捅,在腳本下載遏考、執(zhí)行完成之前,用戶在界面上什么都看不到蓝谨;

注意:dom樹什么時候解析完灌具,是html元素解析完成之后才算解析完。不解析完就不會生成render樹之類的譬巫,界面沒有顯示咖楣。
在div后面又一大堆script標(biāo)簽,一部分瀏覽器為了優(yōu)化缕题,會將這部分div先進行dom截歉,然后render tree,layout painting烟零,進行顯示出來瘪松。但是script后面的dom元素是不會進行顯示的咸作。

4.解決方法

為了解決這個問題,script元素給我們提供了兩個屬性(attribute):defer和async宵睦。

5.2 defer屬性

image.png
  1. defer 屬性告訴瀏覽器不要等待腳本下載记罚,而繼續(xù)解析HTML,構(gòu)建DOM Tree壳嚎。 腳本會由瀏覽器來進行單獨地下載桐智,但是不會阻塞DOM Tree的構(gòu)建過程;
    如果腳本提前下載好了烟馅,也不會立即執(zhí)行说庭,它會等待DOM Tree構(gòu)建完成,在DOMContentLoaded事件之前先執(zhí)行defer中的代碼郑趁;
    DOMContentLoaded事件就是內(nèi)容加載完畢刊驴,也就是dom樹構(gòu)建完成的時候。瀏覽器先去執(zhí)行defer中的代碼寡润,因為defer里面的js有可能操作dom捆憎。然后再去回調(diào)DOMContentLoaded事件。
  2. 所以DOMContentLoaded總是會等待defer中的代碼先執(zhí)行完成梭纹。
  3. 另外多個帶defer的腳本是可以保持正確的順序執(zhí)行的躲惰。
    ? 從某種角度來說,defer可以提高頁面的性能变抽,并且推薦放到head元素中础拨;
    ? 注意:defer僅適用于外部腳本,對于script默認內(nèi)容會被忽略瞬沦。

5.2.1 舉例1:不阻塞后面的東西去構(gòu)建太伊。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">app</div>
    <div id="title">title</div>
    <div id="nav">nav</div>
    <div id="product">product</div>
 <!-- 加上defer以后,js文件的下載和執(zhí)行逛钻,不會影響后面的DOM Tree的構(gòu)建 -->
    <script src="./test.js"></script>
    <h1>哈哈哈哈</h1>
  </body>
</html>

test.js

console.log('test')
debugger
var boxEl = document.querySelector('.box')
console.log(boxEl)

這個時候如果沒有defer僚焦,打開頁面,打開開發(fā)者模式曙痘,之后刷新芳悲,哈哈哈是沒有加載出來的,因為debugger阻塞了dom渲染边坤。


image.png
 <body>
    <div id="app">app</div>
    <div id="title">title</div>
    <div id="nav">nav</div>
    <div id="product">product</div>

    <script src="./test.js" defer></script>
    <h1>哈哈哈哈</h1>
  </body>

如果給script標(biāo)簽defer屬性名扛,是會出現(xiàn)哈哈哈的,因為defer不會影響dom的渲染茧痒。defer你自己去一邊下載去了肮韧,你下載好以后等著,等我對dom樹生成好以后去執(zhí)行你。


image.png

5.2.2 DOMContentLoaded事件之前執(zhí)行

<body>
    <div id="app">app</div>
    <div id="title">title</div>
    <div id="nav">nav</div>
    <div id="product">product</div>
    <!-- 加上defer以后弄企,js文件的下載和執(zhí)行超燃,不會影響后面的DOM Tree的構(gòu)建 -->
    <script src="./test.js" defer></script>
    <script>
      window.addEventListener('DOMContentLoaded', () => {
        console.log('DOMContentLoaded')
      })
    </script>
    <h1 class="box">哈哈哈哈</h1>
  </body>

test.js

console.log('test')
var boxEl = document.querySelector('.box')
console.log(boxEl)

打印結(jié)果

test
test.js:3 <h1 class="box">哈哈哈哈</h1>
index.html:18 DOMContentLoaded

defer是在DOMContentLoaded事件執(zhí)行的。在defer中是可以操作dom的拘领,因為dom樹已經(jīng)構(gòu)建完成了意乓。

總結(jié)1:加上defer以后,js文件的下載和執(zhí)行约素,不會影響后面的DOM Tree的構(gòu)建
總結(jié)2: 在defer中是可以操作dom的届良,因為dom樹已經(jīng)構(gòu)建完成了。
總結(jié)3:defer代碼是在DOMContentLoaded事件觸發(fā)之前執(zhí)行的圣猎。
總結(jié)4:另外多個帶defer的腳本是可以保持正確的順序執(zhí)行的
test.js

console.log('------------------------------')
console.log('i am test js')
var boxEl = document.querySelector('.box')
console.log(boxEl)
console.log('set message to "test message"')
var message = 'test message'
console.log('------------------------------')

demo.js

console.log('------------------------------')
console.log('i am demo js')
console.log(message)
console.log('------------------------------')

index.html

<body>
    <div id="app">app</div>
    <div id="title">title</div>
    <div id="nav">nav</div>
    <div id="product">product</div>
    <!-- 加上defer以后士葫,js文件的下載和執(zhí)行,不會影響后面的DOM Tree的構(gòu)建 -->
    <script src="./test.js" defer></script>
    <script src="./demo.js" defer></script>
    <script>
      window.addEventListener('DOMContentLoaded', () => {
        console.log('DOMContentLoaded')
      })
    </script>
    <h1 class="box">哈哈哈哈</h1>
  </body>

test.js一定是在demo之前執(zhí)行的送悔,就是意味著demo可以使用test中的變量

------------------------------
test.js:2 i am test js
test.js:4 <h1 class="box">哈哈哈哈</h1>
test.js:5 set message to "test message"
test.js:7 ------------------------------
demo.js:1 ------------------------------
demo.js:2 i am demo js
demo.js:3 test message
demo.js:4 ------------------------------
index.html:19 DOMContentLoaded

從某種角度來說为障,defer可以提高頁面的性能,并且推薦放到head元素中放祟;
提高頁面性能是因為使用defer不會阻塞dom tree的構(gòu)建 。
一般把defer放到head里面呻右,提前告訴瀏覽器跪妥,讓瀏覽器先去下載,domtree構(gòu)建声滥,比起放到最后讓他下載會比較提高速度眉撵。dom tree構(gòu)建完了,你才去下載落塑,瀏覽器還是要等纽疟。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="./test.js" defer></script>
    <script src="./demo.js" defer></script>
  </head>
  <body>
    <div id="app">app</div>
    <div id="title">title</div>
    <div id="nav">nav</div>
    <div id="product">product</div>

    <script>
      window.addEventListener('DOMContentLoaded', () => {
        console.log('DOMContentLoaded')
      })
    </script>
    <h1 class="box">哈哈哈哈</h1>
  </body>
</html>

這么加是沒有意義的。
defer僅適用于外部腳本憾赁,對于script默認內(nèi)容會被忽略污朽。


<body>
    <div id="app">app</div>
    <div id="title">title</div>
    <div id="nav">nav</div>
    <div id="product">product</div>

    <script defer>
      window.addEventListener('DOMContentLoaded', () => {
        console.log('DOMContentLoaded')
      })
    </script>
    <h1 class="box">哈哈哈哈</h1>
  </body>

5.3 async屬性

image.png
  1. async 特性與 defer 有些類似,它也能夠讓腳本不阻塞頁面.
    舉例:
    test.js
console.log('------------------------------')
console.log('i am test js')
debugger
var boxEl = document.querySelector('.box')
console.log(boxEl)
console.log('set message to "test message"')
var message = 'test message'
console.log('------------------------------')

index.html

<body>
    <div id="app">app</div>
    <div id="title">title</div>
    <div id="nav">nav</div>
    <div id="product">product</div>
    <script src="./test.js" async></script>
    <script defer>
      window.addEventListener('DOMContentLoaded', () => {
        console.log('DOMContentLoaded')
      })
    </script>
    <h1 class="box">哈哈哈哈</h1>
  </body>

然后打開頁面龙考,打開開發(fā)者工具蟆肆,刷新頁面,發(fā)現(xiàn)哈哈哈也是顯示的晦款。


image.png
DOMContentLoaded
test.js:1 ------------------------------
test.js:2 i am test js

打印結(jié)果

  1. async是讓一個腳本完全獨立的
  • async腳本不能保證順序炎功,它是獨立下載、獨立運行缓溅,不會等待其他腳本蛇损;
  • async不會能保證在DOMContentLoaded之前或者之后執(zhí)行;
    它只要下載下來之后就立刻馬上執(zhí)行,不用等到dom樹構(gòu)建完成以后才執(zhí)行淤齐。
    所以它用起來比較危險股囊,1. 它不能隨意的操作dom,有可能它下載下來執(zhí)行的時候dom樹構(gòu)建完成床玻,也有可能下載完成執(zhí)行的時候dom樹還沒構(gòu)建完成毁涉。這時候拿到的就是null。如果想使用锈死,就判斷一下是不是null贫堰,不是的話再使用。
  1. 而且他也不能保證其他async腳本的順序待牵。
<body>
    <div id="app">app</div>
    <div id="title">title</div>
    <div id="nav">nav</div>
    <div id="product">product</div>
    <script src="./test.js" async></script>
    <script src="./demo.js" async></script>
    <script>
      window.addEventListener('DOMContentLoaded', () => {
        console.log('DOMContentLoaded')
      })
    </script>
    <h1 class="box">哈哈哈哈</h1>
  </body>

這里面的test和demo兩個js文件其屏,并不能保證誰先下載執(zhí)行完。
這個代碼里面缨该,
DOMContentLoaded和demo偎行,test誰先執(zhí)行是不知道的,沒有順序贰拿。

  1. defer通常用于需要在文檔解析后操作DOM的JavaScript代碼蛤袒,并且對多個script文件有順序要求的;
  2. async通常用于獨立的腳本膨更,對其他腳本妙真,甚至DOM沒有依賴的;

6.瀏覽器對渲染內(nèi)容進行優(yōu)化

瀏覽器對標(biāo)準(zhǔn)進行改進荚守,對渲染內(nèi)容進行優(yōu)化珍德,不會等到整個html標(biāo)簽解析完成以后再去構(gòu)建dom tree,再render tree等等進行顯示矗漾。
比如說是一個script里面有代碼锈候,寫了個debuuger,打開頁面敞贡,打開開發(fā)者工具泵琳,執(zhí)行,這個時候嫡锌,script阻塞了dom樹的生成虑稼,頁面應(yīng)該啥也沒有,但是script以前的dom元素是可以看見的势木,這是因為瀏覽器對渲染內(nèi)容做了優(yōu)化蛛倦。
渲染引擎會力求盡快地將內(nèi)容顯示再屏幕上,它不必等到整個html文檔解析完畢之后啦桌,就開始構(gòu)建render tree和layout溯壶,painting及皂。 這也就是script前面的dom可以看見的原因。但是script阻塞dom樹渲染且改,所以script后面的哈哈哈是看不見的验烧。
標(biāo)準(zhǔn)是標(biāo)準(zhǔn),瀏覽器怎么實現(xiàn)標(biāo)準(zhǔn)就不一定了又跛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碍拆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子慨蓝,更是在濱河造成了極大的恐慌感混,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件礼烈,死亡現(xiàn)場離奇詭異弧满,居然都是意外死亡,警方通過查閱死者的電腦和手機此熬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門庭呜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人犀忱,你說我怎么就攤上這事募谎。” “怎么了阴汇?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵近哟,是天一觀的道長。 經(jīng)常有香客問我鲫寄,道長,這世上最難降的妖魔是什么疯淫? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任地来,我火速辦了婚禮,結(jié)果婚禮上熙掺,老公的妹妹穿的比我還像新娘未斑。我一直安慰自己,他們只是感情好币绩,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布蜡秽。 她就那樣靜靜地躺著,像睡著了一般缆镣。 火紅的嫁衣襯著肌膚如雪芽突。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天董瞻,我揣著相機與錄音寞蚌,去河邊找鬼田巴。 笑死,一個胖子當(dāng)著我的面吹牛挟秤,可吹牛的內(nèi)容都是我干的壹哺。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼艘刚,長吁一口氣:“原來是場噩夢啊……” “哼管宵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起攀甚,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤箩朴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后云稚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體隧饼,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年静陈,在試婚紗的時候發(fā)現(xiàn)自己被綠了燕雁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡鲸拥,死狀恐怖拐格,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刑赶,我是刑警寧澤捏浊,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站撞叨,受9級特大地震影響金踪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜牵敷,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一胡岔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枷餐,春花似錦靶瘸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至润匙,卻和暖如春诗眨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背孕讳。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工辽话, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肄鸽,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓油啤,卻偏偏與公主長得像典徘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子益咬,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 前言 瀏覽器的內(nèi)核是指支持瀏覽器運行的最核心的程序逮诲,分為兩個部分的,一是渲染引擎幽告,另一個是JS引擎梅鹦。渲染引擎在不同...
    前端三少爺閱讀 428評論 0 5
  • 一、認識瀏覽器內(nèi)核Trident(IE)Gecko(火狐)Blink(Chrome冗锁、Opera)Webkit(Sa...
    chan7788閱讀 299評論 0 0
  • 瀏覽器如何渲染網(wǎng)頁 要了解瀏覽器渲染頁面的過程齐唆,首先得知道一個名詞——關(guān)鍵渲染路徑。關(guān)鍵渲染路徑是指瀏覽器從最初接...
    oWSQo閱讀 32,888評論 5 74
  • 瀏覽器如何渲染網(wǎng)頁 要了解瀏覽器渲染頁面的過程冻河,首先得知道一個名詞——關(guān)鍵渲染路徑箍邮。關(guān)鍵渲染路徑是指瀏覽器從最初接...
    三省吾身_9862閱讀 196評論 0 0
  • 原文鏈接 http://blog.poetries.top/2018/12/22/browser-render 關(guān)...
    程序員poetry閱讀 8,281評論 1 10