VueJS設計實戰一書
先前不知道在哪個社群平台刷到有人在分享關於這本書,內容是介紹關於VueJS的設計概念,以喜歡了解更底層原理的我來說,就買來看看,重點是連Vue框架設計者Evan You都寫推薦,作者霍春陽也是Vue開發團隊的一員,這裡會是我讀完理解後的筆記,如果有興趣的人可以去買來看,描述算是輕鬆易懂,但是要有一定的熟悉VueJS、Javascript的基礎知識,不然可能還是不知道他在講什麼。
命令式與聲明式
Vue這個框架是屬於聲明式的,這兩個是什麼且又有什麼差異?
命令式:在書中的範例提到如下
1 | // jquery版 |
聲明式(也是就是Vue的做法):
1 | <div @click="() => alert('ok')">hello world</div> |
這裡意思是說,我要建立一個div tag,並且在這裡綁定一個事件click,當點擊時跳出alert視窗。
在框架中希望的是寫成上述的樣式後由框架處理後續,把命令式這些行為給完成,這個好處是可以讓使用者更容易撰寫程式碼且心智負擔更小。
效能
前面提到的命令式與聲明式的寫法,但肯定有優缺點,聲明式的程式碼基本上不可能優於命令式的程式碼。
例子:
以命令式來說,如果要更改上面的div的內容只需直接以命令方式直接修改
1 | div.textContent = 'hello Vue3' |
上述已經是最極致效能的做法,也就是直接修改其內容
但在聲明式如Vue寫法要如何做?
1 | <!-- 舊的 --> |
在框架中希望做到的是找到兩者個差異後只更新變化地方,但是最終要做的事還是與命令式一樣
1 | div.textContent = 'hello Vue3' |
這裡假設
- 命令式修改內容的效能消耗 = A
- 聲明式修改內容的效能消耗 = B + A
這個 B 指的是聲明式需要找出內容差異的效能消耗,而A是要修改DOM的效能消耗,與命令式是一樣的,所以以理論上來說聲明式的效能不會高過於命令式,因為聲明式程式碼封裝了命令式的程式碼,並且要找出內容差異的效能消耗。
那為什麼框架要選擇以聲明式的方式來寫呢?主要是為了程式碼的維護性,讓開發者更直觀地去開發。
Virtual DOM 虛擬DOM
為什麼要有虛擬DOM?
主要是如前面所說的B的部分,也就是希望儘可能減少 找出差異的效能消耗
,如果可以盡可能減少就可以無限逼近命令式程式碼的效能。
前面提到的都是用如document.createElement()的方式來對DOM做操作,但在jQuery中是使用innerHTML的方式來操作頁面如下的方式
1 | const html = '<div><span>hello world</span></div>' |
這裡涉及最主要的一件事是要解析html字串變成DOM,DOM層面的計算是非常耗時的,DOM的運算會遠比Javascript的運算的效能來得差。
在書中有解釋到執行1000次建立js的物件的時間遠比使用document.createElement()的方式要快,主要是要表示建立DOM樹是很花時間的。
- innerHTML的頁面建立效能:HTML字串拼接的計算量 + innerHTML的DOM樹建立的計算量
關於虛擬DOM的建立效能,第一步要建立JS物件,可以理解成對應真實DOM的描述物件,再來就是要走訪(遍歷)虛擬DOM樹來建立真實DOM,所以計算量如下:
- 虛擬DOM的頁面建立效能:建立JS物件的計算量 + 訪問虛擬DOM並且建立真實DOM的計算量
效能量級
看上述兩者的頁面建立效能似乎差異不大,但是可以注意到使用innerHTML的方式是每次只要有修改內容時,整個舊的DOM就會被銷毀並且重新建立新的DOM樹。
而在虛擬DOM中,會是重新建立新的虛擬DOM樹,比較新舊的DOM樹並且找出有被修改的元素,對於真實的DOM樹部分只修改變動的地方。
可以看到在虛擬DOM中,除了前面提到的建立新的JS物件之外,還多做一件事情就是比較虛擬與真實DOM樹的差異,但因為都是在JS層面運算,相效於DOM層面運算的量級是小非常多的,而且在虛擬DOM中,只需要去修改真實DOM必須被修改的部分,效能與innerHTML相比,一下子就拉開差距。
在頁面越大對於innerHTML的效能就會越來越差,所以虛擬DOM的方式是一個非常好的選擇,不過要注意的是虛擬DOM的更新會因為資料變化量而影響到效能,也就是頁面中有越多的變化就會越吃效能。
心智負擔、維護性、效能
innerHTML | 虛擬DOM | 原生JavaScript |
---|---|---|
心智負擔中等 | 心智負擔低 | 心智負擔高 |
效能差 | 效能不錯 | 效能高 |
所以為心智負擔,意思是說對於開發者的開發體驗等等,不需要為了效能去寫原生JavaScript,也可以透過虛擬DOM來達到不錯的效能。