摘要:而瀏覽器渲染與密切相關,因此只有了解其中工作原理才能讓更好地工作。瀏覽器也稱為布局渲染方式瓦片渲染流暢動畫總結參考文章瀏覽器用戶界面包括地址欄前進后退按鈕書簽菜單等。瀏覽器引擎在用戶界面和渲染引擎之間傳送指令。渲染引擎負責顯示請求的內容。
singsong: 文本是自己看了一些不錯資料整理出來的,對該知識點感興趣的同學可以查看參考文章小節。
??最新內容請以github上的為準??
為什么要寫這篇文章?主要為 CSS 優化工作打一下基礎。要編寫高性能的網站和應用,除了確保編寫的代碼盡可能高效地運行外,還需要確保頁面性能,刷新頻率盡量到達 60FPS。這就需要了解瀏覽器是如何進行渲染的。而瀏覽器渲染與 CSS 密切相關,因此只有了解其中工作原理才能讓 CSS 更好地工作。
另外,接下來會出一篇優化實戰文章,會涉及 JavaScript 和 CSS 一些優化。其中關于 JavaScript 的優化之前已進行過介紹:常見的 JavaScript 內存泄露。本文是對 CSS 優化進行一個補充。
Contents瀏覽器
DOM tree
CSSOM tree
RenderObject tree(也稱為 Render tree)
Layout(布局)
RenderLayer tree
Rendering(渲染方式)
GrphicsLayer tree
Tiled Rendering(瓦片渲染)
High Performance Animations(流暢動畫)
總結
參考文章
瀏覽器用戶界面(User Interface):包括地址欄、前進/后退按鈕、書簽菜單等。除了瀏覽器主窗口顯示的您請求的頁面外,其他顯示的各個部分都屬于用戶界面。
瀏覽器引擎(Browser engine):在用戶界面(User Interface)和渲染引擎(Rendering engine)之間傳送指令。
渲染引擎(Rendering engine):負責顯示請求的內容。如果請求的內容是 HTML,它就負責解析 HTML 和 CSS 內容,并將解析后的內容顯示在屏幕上。
網絡(Networking):用于網絡調用,比如 HTTP 請求。其接口與平臺無關,并為所有平臺提供底層實現。
JavaScript 解釋器(JavaScript Interperter):用于解析和執行 JavaScript 代碼。
用戶界面后端(UI Backend):用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與平臺無關的通用接口,而在底層使用操作系統的用戶界面方法。
數據存儲(Data storage):這是持久層。瀏覽器需要在硬盤上保存各種數據,例如 Cookies。瀏覽器還支持諸如 localStorage,IndexedDB,WebSQL 和 FileSystem 之類的存儲機制。
本文主要介紹瀏覽器的渲染,即渲染引擎(Rendering engine)負責的工作: 將請求的 HTML 和 CSS 內容解析并渲染在屏幕上。
DOM treeDOM:Document Object Model,文檔對象模型。它可以以一種獨立于平臺和語言的方式,訪問和修改一個文檔的內容和結構。它定義了一組與平臺,語言無關的接口,該接口允許編程語言動態地訪問和修改結構化文檔。基于 DOM 表示的文檔被描述成一個樹形結構,使用 DOM 的接口可以對 DOM 樹進行操作。
這里以一個實例展開講解,如下 HTML 結構包含一些文本和一張圖片:
Critical Path Hello web performance students!
瀏覽器是如何處理這個 HTML 頁面:
轉換(Conversion):瀏覽器從磁盤或網絡讀取 HTML 的字節碼,并根據文件的指定編碼(例如 UTF-8)將其轉換成對應的字符。
令牌化(Tokenizing):瀏覽器將字符串轉換成W3C HTML5 標準規定的各種 token,例如、,以及其他尖括號內的字符串。每個 token 都具有一定特殊含義和規則。
詞法分析(Lexing):將 token 轉換成定義其屬性和規則的“對象”。
DOM tree:HTML 標簽定義了不同標簽之間的關系(某些標簽包含在其他標簽中),所創建的對象鏈接在樹狀數據結構中,該數據結構還捕獲原始標簽中定義的父——子關系:HTML 是 body 的父對象,body 是段落的父對象,依此類推。
整個過程的最終輸出是 HTML 頁面的 DOM tree,后續瀏覽器對頁面進一步的所有處理都會用到它。瀏覽器每次處理 HTML 標簽時,都會完成以上所有步驟:將字節轉換成字符,確定 token,將 token 轉換成節點,然后構建 DOM tree。
CSSOM treeCSSOM:CSS Object Model,CSS 對象模型。CSSOM 定義了 JavaScript 訪問樣式的能力和方式。它是在 DOM 中的一些接口中,加入獲取和操作 CSS 屬性或接口的 JavaScript 接口,因而 JavaScript 可以動態操作 CSS 樣式。DOM 提供了接口讓 JavaScript 修改 HTML 文檔,CSSOM 提供了接口讓 JavaScript 獲得和修改 CSS 代碼設置的樣式信息。
在瀏覽器構建 DOM 遇到 link 標簽時,該標簽引用一個外部 CSS 樣式表:style.css。由于預見到需要利用該資源來渲染頁面,它會立即發出對該資源的請求,并返回以下內容:
body { font-size: 16px } p { font-weight: bold } span { color: red } p span { display: none } img { float: right }
與處理 HTML 時類似,需要將收到的 CSS 規則轉換成某種瀏覽器能夠理解和處理的內部表示。因此會重復 HTML 過程,不過是對 CSS 而不是 HTML:
將 CSS 字節轉換成字符,接著轉換成 token 和節點,最后將它們鏈接到 CSSOM tree 結構中:
CSSOM tree 可以用于確定節點對象的計算樣式。如 span 標記包含了color:red樣式和繼承于 body 標記的font-size:16px樣式;
RenderObject tree(也稱為 Render tree)在 DOM tree 中,存在不可見與可見節點之分。顧名思義,不可見節點是不需要繪制最終頁面中的節點,如meta、head、script等,以及通過 CSS 樣式display:none隱藏的節點。相反可見節點是用戶可見的,如body、div、span、canvas、img等。對于這些可見節點,瀏覽器需要將它們的內容繪制到最終的頁面中,所以瀏覽器會為它們建立對應的 RenderObject 對象。一個 RenderObject 對象保存了為繪制 DOM 節點的各種信息。這些 RenderObject 對象與 DOM 對象類似,也構成一棵樹,稱為RenderObject tree。RenderObject tree 是基于 DOM tree 建立起來的一棵新樹,是為了布局計算和渲染等機制而構建的一種新的內部表示。RenderObject tree 節點與 DOM tree 節點不是一一對應關系。因為創建一個 RenderObject 對象需要滿足如下規則:
DOM tree 的 document 節點
DOM tree 中的可見節點,如html、body、div等。而瀏覽器不會為不可見節點創建 RenderObject 節點。
某些情況下瀏覽器需要創建匿名的 RenderObject 節點,該節點不對應 DOM 樹中的任何節點。
RenderObject 對象構成了 RenderObject tree,每個 RenderObject 對象保存了為繪制 DOM 節點的計算樣式。RenderObject tree 也可以理解成由 CSSOM tree 和 DOM tree 合并成:
Layout(布局)當瀏覽器創建 RenderObject 對象之后,每個對象并不知道自己在設備視口內的位置、大小等信息。瀏覽器根據盒模型(Box-model)來計算它們的位置、大小等信息的過程稱為布局計算(重排)。布局計算是一個遞歸的過程,這是因為一個節點的大小通常需要先計算它的孩子節點的位置、大小等信息。為了計算節點在頁面中的確切大小和位置,瀏覽器會從 RenderObject tree 的根節點開始進行遍歷。
實例:
Critial Path: Hello world! Hello world!
頁面包含了兩個嵌套 div:父 div 將其的顯示尺寸設置為 viewport 寬度的 50%,子 div 將其寬度設置為其父項的 50%,即 viewport 寬度的 25%。
RenderLayer tree瀏覽器渲染引擎并不是直接使用 RenderObject tree 進行繪制,為了方便處理 Positioning(定位),Clipping(裁剪),Overflow-scroll(頁內滾動),CSS Transform/Opacity/Animation/Filter,Mask or Reflection,Z-indexing(Z 排序)等,瀏覽器需要會為一些特定的 RenderObject 生成對應的 RenderLayer,并生成一棵對應的 RenderLayer tree。而這些特定的 RenderObject 跟對應的 RenderLayer 就是直屬的關系,如果它們的子節點如果沒有對應的 RenderLayer,就從屬于父節點的 RenderLayer。最終,每一個 RenderObject 都會直接或者間接地從屬于一個 RenderLayer。因此 RenderObject 節點與 RenderLayer 節點不是一一對應關系,而是一對多的關系。那需要滿足什么條件,渲染引擎才為 RenderObject 建立對應的 RenderLayer:
It"s the root object for the page
It has explicit CSS position properties (relative, absolute or a transform)
It is transparent
Has overflow, an alpha mask or reflection
Has a CSS filter
Corresponds to element that has a 3D (WebGL) context or an accelerated 2D context
Corresponds to a element
翻譯:
DOM tree 的 Document 節點對應的 RenderObject 節點和 HTML 節點對應的 RenderObject 節點
顯式指定 CSS position 屬性的 RenderObject 節點
有透明度的 RenderObject 節點
有 overflow,alpha 和 reflection 的樣式 RenderObject 節點
有 filter 樣式的 RenderObject 節點
使用 Canvas 2D 和 3D(WebGL)技術的 RenderObject 節點
video 元素對應的 RenderObject 節點
每個 RenderLayer 對象可以想象成圖像中一個圖層,各個圖層疊加構成了一個圖像。瀏覽器會遍歷 RenderLayer tree,再遍歷從屬這個 RenderLayer 的 RenderObject,RenderObject 對象存儲有繪制信息,并進行繪制。RenderLayer 和 RenderObject 共同決定了最終呈現的網頁內容,RenderLayer tree 決定了網頁的繪制的層次順序,而從屬于 RenderLayer 的 RenderObject 決定了該 RenderLayer 的內容。
Rendering(渲染方式)在完成構建 RenderLayer tree 之后,瀏覽器會使用圖形庫將其構建的渲染模型繪制出來,該過程分為兩個階段:
繪制:將從屬每個 RenderLayer 圖層上的 RenderObject 繪制在其 RenderLayer 上。即繪制(Paint)或者光柵化(Rasterization),將一些繪圖指令轉換成真正的像素顏色值。
軟件繪圖:CPU 來完成繪圖操作
硬件加速繪圖:GPU 來完成繪圖操作
合成(compositing):將各個 RenderLayer 圖層合并成到一個位圖(Bitmap)中。同時還可能包括位移(Translation),縮放(Scale),旋轉(Rotation),Alpha 合成等操作。
渲染引擎的渲染,目前有三種網頁的渲染方式:
硬件加速合成(Accelerated Compositing):使用 GPU 來完成合成工作。
合成化渲染:使用合成(compositing)技術的渲染稱。
軟件渲染方式:使用 CPU 來繪制每個 RenderLayer 圖層的內容(RenderObject)到一個位圖,即一塊 CPU 使用的內存空間。繪制每一層的時候都會使用該位圖,區別在于繪制的位置可能不一樣,繪制順序按照從后到前。因此軟件渲染機制是沒有合成階段的。
硬件加速渲染的合成化渲染方式:使用 GPU 來繪制所有合成層,并使用 GPU 硬件來加速合成。
軟件繪圖的合成化渲染方式: 某些合成層使用 CPU 來繪圖,另外一些使用 GPU 來繪制。對于使用 CPU 來繪制的圖層,該層的繪制結果會先保存在 CPU 內存中,之后會被傳輸到 GPU 內存中,然后再使用 GPU 來完成合成工作。
第二種和第三種渲染方式,都是使用了合成化渲染技術,合成工作也都是由 GPU 來做。對于常見的 2D 繪圖操作,使用 GPU 來繪圖不一定比使用 CPU 繪圖在性能上有優勢,例如繪制文字、點、線等。原因是 CPU 的使用緩沖機制有效減少了重復繪制的開銷而且不需要考慮與 GPU 并行。另外,GPU 的內存資源相對 CPU 的內存資源來說比較緊張,而且網頁的分層使得 GPU 的內存使用相對比較多。鑒于此,就目前的情況來看,三者都存在是有其合理性的,下面分析一下它們的特點:
軟件渲染是目前很常見的技術,也是瀏覽器最早使用的渲染方式。這一技術比較節省內存,特別是寶貴的 GPU 內存,但是軟件渲染只能處理 2D 方面的操作。簡單的網頁沒有復雜繪圖或者多媒體方面的需求,軟件渲染方式就比較合適來渲染該類型的網頁。問題是,一旦遇上了 HTML5 的很多新技術,軟件渲染顯得無能為力,一是因為能力不足;二是因為性能不好,例如視頻、Canvas 2D 等。所以,軟件渲染技術被用的越來越少,特別是在移動領域。軟件渲染同硬件加速渲染另外一個很不同的地方就是對更新區域的處理。當網頁中有一個更新小型區域的請求(如動畫)時,軟件渲染可能只需要計算一個極小的區域,而硬件渲染可能需要重新繪制其中的一層或者多層,然后再合成這些層。硬件渲染的代價可能會大得多。
對于硬件加速的合成化渲染方式來說,每個層的繪制和所有層的合成均使用 GPU 硬件來完成,這對需要使用 3D 繪圖的操作來說特別合適。這種方式下,在 RenderLayer 樹之后,瀏覽器還需要建立更多的內部表示,目的是支持硬件加速機制,這顯然會消耗更多的內存資源。但是,一方面,硬件加速機制能夠支持現在所有的 HTML5 定義的 2D 或者 3D 繪圖標準;另一方面,關于更新區域的討論,如果需要更新某個層的一個區域,因為軟件渲染沒有為每一層提供后端存儲,因而它需要將和這個區域有重疊部分的所有層次的相關區域一次從后往前重新繪制一遍,而硬件加速渲染只需要重新繪制更新發生的層次,因而在某些情況下,軟件渲染的代價又變得更大。當然,這取決于網頁的結構和渲染策略。
軟件繪圖的合成化渲染方式結合了前面兩種方式的優點,這時因為很多網頁可能既包含基本的 HTML 元素,也包含一些 HTML5 新功能,使用 CPU 繪圖方式來繪制某些層,使用 GPU 來繪制其他一些層。原因當然是前面所述的基于性能和內存方面綜合考慮的結果。
瀏覽器還可以使用多線程的渲染架構,將網頁內容繪制到后端存儲的操作放到另外一個獨立的線程(繪制線程),而原來線程轉為合成線程,繪制線程跟合成線程之間可以使用同步,部分同步,完全異步等作業模式,讓瀏覽器可以在性能與效果之間根據需要進行選擇。GrphicsLayer tree
對于軟件渲染而言,到 RenderLayer tree 就結束了,后面不會建立其它額外的樹來對應于 RenderLayer tree。但是,對于硬件渲染來說,在 RenderLayer tree 之后,瀏覽器渲染引擎為硬件渲染提供了更多的內部結構來支持這個機制。
在硬件加速渲染的合成化渲染和軟件繪圖的合成化渲染架構下,一個 RenderLayer 對象如果需要后端存儲,它會創建一個 RenderLayerBacking 對象,該對象負責 Renderlayer 對象所需要的各種存儲。理想情況下,每個 RenderLayer 都可以創建自己的后端存儲,事實上不是所有 RenderLayer 都有自己的 RenderLayerBacking 對象。如果一個 RenderLayer 對象被像樣的創建后端存儲,那么將該 RenderLayer 稱為合成層(Compositing Layer)。
哪些 RenderLayer 對象可以是合成層?如果一個 RenderLayer 對象具有以下的特征之一,那么它就是合成層:
Layer has 3D or perspective transform CSS properties
Layer is used by < video> element using accelerated video decoding
Layer is used by a < canvas> element with a 3D context or accelerated 2D context
Layer is used for a composited plugin
Layer uses a CSS animation for its opacity or uses an animated webkit transform
Layer uses accelerated CSS filters
Layer with a composited descendant has information that needs to be in the composited layer tree, such as a clip or reflection
Layer has a sibling with a lower z-index which has a compositing layer (in other words the layer is rendered on top of a composited layer)
翻譯:
RenderLayer 具有 3D 或透視轉換的 CSS 屬性
RenderLayer 包含使用硬件加速的視頻解碼技術的元素
RenderLayer 包含使用硬件加速的 2D 或 WebGL-3D 技術的元素
RenderLayer 使用了合成插件。
RenderLayer 使用了opacity或transform動畫
RenderLayer 使用了硬件加速的 CSS Filters 技術
RenderLayer 后代中包含了一個合成層(如有 clip 或 reflection 屬性)
RenderLayer 有一個 z-index 比自己小的合成層(即在一個合成層之上)
每個合成層都有一個 RenderLayerBacking,RenderLayerBacking 負責管理 RenderLayer 所需要的所有后端存儲,因為后端存儲可能需要多個存儲空間。在瀏覽器(WebKit)中,存儲空間使用類 GraphicsLayer 來表示。瀏覽器會為這些 RenderLayer 創建對應的 GraphicsLayer,不同的瀏覽器需要提供自己的 GrphicsLayer 實現用于管理存儲空間的分配,釋放,更新等等。擁有 GrphicsLayer 的 RenderLayer 會被繪制到自己的后端存儲,而沒有 GrphicsLayer 的 RenderLayer 它們會向上追溯有 GrphicsLayer 的父/祖先 RenderLayer,直到 Root RenderLayer 為止,然后繪制在有 GrphicsLayer 的父/祖先 RenderLayer 的存儲空間,而 Root RenderLayer 總是會創建一個 GrphicsLayer 并擁有自己獨立的存儲空間。在將每個合成圖層包含的 RenderLayer 內容繪制在合成層的后端存儲中,這里繪制可以是軟件繪制或硬件繪制。接著由合成器(Compositor)將多個合成層合成起來,形成最終用戶可見的網頁,實際上就是一張圖片。
GraphicsLayer 又構成了一棵與 RenderLayer 并行的樹,而 RenderLayer 與 GraphicsLayer 的關系有些類似于 RenderObject 與 RenderLayer 之間的關系。如下是 DOM tree、RenderObject tree、RenderLayer tree、GraphicsLayer tree關系圖:
這樣可以合并一些 RenderLayer 層,從而減少內存的消耗。其次,合并之后,減少了合并帶來的重繪性能和處理上的困難。在硬件加速渲染的合成化渲染和軟件繪圖的合成化渲染架構下,RenderLayer 的內容變化,只需要更新所屬的 GraphicsLayer 的緩存即可,而緩存的更新,也只需要繪制直接或者間接屬于這個 GraphicsLayer 的 RenderLayer,而不是所有的 RenderLayer。特別是一些特定的 CSS 樣式屬性的變化,實際上并不引起內容的變化,只需要改變一些 GraphicsLayer 的混合參數,然后重新混合即可,而混合相對繪制而言是很快的,這些特定的 CSS 樣式屬性我們一般稱之為是被加速的,不同的瀏覽器支持的狀況不太一樣,但基本上 CSS Transform & Opacity 在所有支持混合加速的瀏覽器上都是被加速的。被加速的 CSS 樣式屬性的動畫,就比較容易達到 60 幀/每秒的流暢效果了。
不過并不是擁有獨立緩存的 RenderLayer 越多越好,太多擁有獨立緩存的 RenderLayer 會帶來一些嚴重的副作用:
它大大增加了內存的開銷,這點在移動設備上的影響更大,甚至導致瀏覽器在一些內存較少的移動設備上無法很好地支持圖層合成加速;
它加大了合成的時間開銷,導致合成性能的下降,而合成性能跟網頁滾動/縮放操作的流暢度又息息相關,最終導致網頁滾動/縮放的流暢度下降,讓用戶覺得操作不夠流暢。
Tiled Rendering(瓦片渲染)通常一個合成層的后端存儲被分割成多個大小相同的瓦片狀的小存儲空間,每個瓦片可以理解為 OpenGL 中的一個紋理,合成層的結果被分開存儲在這些瓦片中。為什么使用瓦片化的后端存儲?
DOM 樹種的 html 元素所在的層可能會比較大,因為網頁的高度很大,如果只是使用一個后端存儲的話,那么需要一個很大的紋理對象,但是實際的 GPU 硬件可能只支持非常有限的紋理大小。
在一個比較大的合成層中,可能只是其中一部分發生變化,根據之前的介紹,需要重新繪制整個層,這樣必然產生額外的開銷,使用瓦片話的后端存儲,就只需要重繪一些存在更新的瓦片。
當層發生滾動的時候,一些瓦片可能不再需要,然后渲染引擎需要一些新的瓦片來繪制新的區域,這些大小相同的后端存儲很容易重復利用。
High Performance Animations(流暢動畫)網頁加載后,繪制新的每一幀,一般都需要經過計算布局(layout)、繪圖(paint)、合成(composite)三階段。因此要想提高頁面性能(或 FPS),需要減少每一幀的時間。而在這三個階段中,layout 和 paint 比較耗時間,而合成需要的時間相對較少一些。
layout如果修改 DOM 元素的 layout 樣式(如 width, heihgt 等),瀏覽器會計算頁面需要 relayout 的元素,然后觸發一個 relayout。被 relayout 的元素,接著會執行繪制,最后進行渲染合并生成頁面。
如果修改 DOM 元素的 paint 樣式(如 color, background 等),瀏覽器會跳過布局,直接執行繪制,再進行合成。
如果修改 DOM 元素的 composite 樣式(如 transform, opacity 等)。瀏覽器會跳過布局和繪制,直接執行合成。該過程是開銷最小的,也是優化著手點。
如果想知道修改任何指定 CSS 樣式會觸發 layout、paint、composite 中的哪一個,請查看CSS 觸發器。
優化可以通過什么途徑進行優化,減少每一幀的時間(避免過多 layout 或 paint):
使用適合的網頁分層技術減少 layout 和 paint。一旦有請求更新,如果沒有分層,渲染引擎可能需要重新繪制所有區域,因為計算更新部分對 GPU 來說可能消耗更多的時間。而網頁分層之后,部分區域的更新可能只在網頁的一層或幾層,而不需要將整個網頁重新繪制。通過重新繪制網頁的一層或幾層,并將它們和其他之前繪制完的層合并起來,既能使用 GPU 的能力,又能夠減少重繪的開銷。
使用合成屬性樣式(opcity、tansform)來完成 tansition 或 animation。當合成器合成時候,每個合成層都可以設置變形屬性:位移(Translate)、縮放(Scale)、旋轉(Rotation)、opacity,這些屬性僅僅改變合成層的變換參數,而不需要 layout 和 paint 操作,極大地減少每一幀的渲染時間。
即使用 GPU 硬件加速,為某些 RenderLayer 創建對應 GraphicsLayer。通過為每一個合成層設置transform屬性來完成 transition 或 animation,有效地避免 relayout 和 repaint 的開銷。
總結本文重點介紹了瀏覽器渲染引擎的渲染過程,涉及了 DOM tree、CSSOM tree、RenderObject tree、RenderLayer tree、GraphicsLayer tree。并對各種渲染模式進行了簡單介紹,其中引入了硬件加速機制,還給出一些優化建議。了解這些知識點對我們開發高性能的 web 應用會有很大的幫助。
參考文章:GPU Accelerated Compositing in Chrome
瀏覽器的工作原理:新式網絡瀏覽器幕后揭秘
構建對象模型
How Rendering Work (in WebKit and Blink)
WebKit 技術內幕
渲染性能
High Performance Animations
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/113232.html
摘要:作者兩年經驗第一家任職的是個小公司第二家算是二線互聯網公司各待了一年吧能有機會去阿里面試很驚喜先來和大家分享一下面試經歷電話面試初探因為還在職的緣故電話面試從晚上點鐘開始持續了半個小時左右一開始的時候特比緊張甚至聲音略有些顫抖簡單自我介紹做 作者兩年經驗, 第一家任職的是個小公司, 第二家算是二線互聯網公司, 各待了一年吧... 能有機會去阿里面試很驚喜! 先來和大家分享一下面試經歷....
摘要:這個階段只有一個方法,該方法在整個生命周期內調用且僅調用一次。在這里進行一些相關的銷毀操作,比如撤銷定時器,事件監聽等等。 詳解 React 生命周期 整個 React 生命周期有3個階段:創建、更新、卸載,每個階段有對應的工作和方法,我們可以看下面這個經典的圖研究一下: showImg(https://segmentfault.com/img/remote/1460000016330...
摘要:而瀏覽器渲染與密切相關,因此只有了解其中工作原理才能讓更好地工作。瀏覽器也稱為布局渲染方式瓦片渲染流暢動畫總結參考文章瀏覽器用戶界面包括地址欄前進后退按鈕書簽菜單等。瀏覽器引擎在用戶界面和渲染引擎之間傳送指令。渲染引擎負責顯示請求的內容。 singsong: 文本是自己看了一些不錯資料整理出來的,對該知識點感興趣的同學可以查看參考文章小節。 ??最新內容請以github上的為準?? 為...
閱讀 3557·2021-08-02 13:41
閱讀 2390·2019-08-30 15:56
閱讀 1519·2019-08-30 11:17
閱讀 1174·2019-08-29 15:18
閱讀 579·2019-08-29 11:10
閱讀 2671·2019-08-26 13:52
閱讀 507·2019-08-26 13:22
閱讀 2948·2019-08-23 15:41