深入淺出vue.js----模板編譯原理

一、概述

(1)在Vue.js中創建HTML並不是只有模板這一種途徑。既可以手動寫渲染函數來創建HTML,也可以在Vue.js中使用JSX來創建HTML。

(2)渲染函數是創建HTML最原始的方法。

(3)模板最終會通過編譯轉換成渲染函數,渲染函數執行後,會得到一份vnode用於虛擬DOM渲染。所以模板編譯其實是配合虛擬DOM進行渲染。

(4)模板編譯所介紹的內容是如何讓虛擬DOM拿到vnode。(模板--》模板編譯--》渲染函數(模板編譯)--》vnode--》用戶界面(虛擬DOM))

(5)Vue.js提供了模板語法,允許聲明式地描述狀態和DOM之間地綁定關係,然後通過模板來生成真實DOM並將其呈現在用戶界面上。

(6)在底層實現上,Vue.js會將模板編譯成虛擬DOM渲染函數。當應用內部地狀態發生變化時,Vue.js可以結合響應式系統,聰明地找出最小數量地組件進行重新渲染以及最少量地進行DOM操作。

二、概念

(1)平時使用模板時,可以在模板中使用一些變量來填充模板,還可以在模板中使用Javascript表達式,又或者是使用一些指令等。這些功能在HTML語法中是不存在的,這多虧了模板編譯賦予了模板強大的功能。

(2)模板編譯的主要目標就是生成渲染函數。而渲染函數的作用是每次執行它,它就會使用當前最新的狀態生成一份新的vnode,然後使用這個vnode進行渲染。

三、將模板編譯成渲染函數

(1)模板編譯分三部分內容

1、將模板解析爲AST。(Abstract Syntax Tree,抽象語法樹)。

2、遍歷AST標記靜態節點。

3、使用AST生成渲染函數。

(2)由於靜態節點不需要總是重新渲染,所以在生成AST之後、生成渲染函數之前這個節點,需要做一個操作,那就說遍歷一遍AST,給所有靜態節點做一個標記,這樣在虛擬DOM中更新節點時,如果發現節點有這個標記,就不會重新渲染它。

(3)這三部分內容在模板編譯中分別抽象出三個模塊來實現各自的功能,分別是

1、解析器。

2、優化器。

3、代碼生成器。

四、解析器

(1)作用:將模板解析成AST

(2)在解析器內部,分成了很多小解析器,其中包括過濾器解析器文本解析器HTML解析器。然後通過一條主線將這些解析器組裝在一起。

(3)在使用模板時,我們可以在其中使用過濾器,而過濾器解析器的作用就說用來解析過濾器的。

(4)文本解析器就是用來解析文本的。其主要作用是用來解析帶變量的文本。不帶變量的文本是一段純文本,不需要使用文本解析器來解析。

Hello {{name}}

(5)HTML解析器,它是解析器中最核心的模塊,它的作用就是解析模板,每當解析到HTML標籤的開始位置、結束位置、文本或則註釋時,都會觸發鉤子函數,然後將相關信息通過參數傳遞進來。

(6)主線上做的事就是監聽HTML解析器。每當觸發鉤子函數時,就生成一個對應的AST節點。生成AST節點前,會根據類型使用不同的方式生成不同的AST。例如,如果是文本節點,就生成文本類型的AST。

(7)這個AST其實和vnode有點類似,都是使用Javascript中的對象來表示節點。

(8)當HTML解析器把所有模板都解析完畢後,AST也就生成好了。

五、優化器

(1)目標:遍歷AST,檢測出所有靜態子樹(永遠都不會發生變化的DOM節點)並給其打標記

(2)當AST中的靜態子樹被打上標記後,每次重新渲染時,就不需要爲打上標記的靜態節點創建新的虛擬節點,而是直接克隆已存在的虛擬節點。

(3)在虛擬DOM的更新操作中,如果發現兩個是同一個節點,正常情況下會對這兩個節點進行更新,但是如果這兩個節點是靜態節點,則可以直接跳過更新節點的流程。

(4)優化器的主要作用是避免一些無用功來提升性能。因爲靜態節點出了首次渲染,後續不需要任何重新渲染操作。

六、代碼生成器

(1)其是模板編譯的最後一步,作用是將AST轉換成渲染函數中的內容,這個內容可以稱爲“代碼字符串”。

<p title="Berwin" @click="c">1</p>

生成後的代碼字符串: 

with(this){ 
	return _c(
		'p',
		{
			attrs:{"title""Berwin"},
			on:{"click":c}
		},
		[_v("1")] 
	)
}

(2)這樣一個代碼字符串最終導出到外界使用時,會將代碼字符串放到函數裏,這個函數叫作渲染函數

(3)當渲染函數被導出到外界後,模板編譯的任務就完成了。

const code = 'with(this){return 'Hello Berwin'}';
const hello = new Function(code);
hello();
//Hello Berwin

(4)渲染函數的作用是創建vnode。渲染函數之所以可以生成vnode,是因爲代碼字符串中會有很多函數調用(例如,上面生成的代碼字符串中有兩個函數調用_c 和 _v),這些函數是虛擬DOM提供的創建vnode的方法。

(5)vnode有很多種類型,不同類型對應不同的創建方法,所以代碼字符串中的_c 和 _v其實都是創建vnode的方法,只是創建vnode的類型不同,例如_c 可以創建元素類型的vnode,而 _v可以創建文本類型的vnode。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章