(四)Vue原理
Vue原理
- Vue原理(大廠必考)
- 面試為何會考察原理
- 面試中如何考察?以何種方式
- Vue原理包括哪些?
- 如何理解MVVM
- 組件化基礎
- “很久以前”就有組件化
- 數據驅動視圖(MVVM,setState)
- Vue MVVM
- 總結
- 監聽data變化的核心API是什么
- Vue響應式
- Proxy有兼容性問題
- Object.defineProperty基本用法
- Object.defineProperty實現響應式
- 如何深度監聽data變化、數組變化
- Object.defineProperty缺點
- 總結
- 虛擬DOM-面試里的網紅
- 虛擬DOM(Virtual DOM)和diff
- 解決方案-vdom
- 通過snabbdom學習vdom
- 用過虛擬DOM嗎?
- snabbdom重點總結
- vdom總結
- 虛擬DOM-diff算法概述
- 樹diff的時間復雜度O(n^3)
- 優化時間復雜度到O(n)
- 深入diff算法源碼
- 生成vnode
- patch函數
- patchVnode函數(vnode對比)
- updateChildren函數
- 虛擬DOM-考點總結和復習
- diff算法總結
- vdom和diff-總結
- 模板編譯前置知識點-with語法
- 模板編譯
- with語法
- vue模板被編譯成什么?
- 編譯模板
- vue組件中使用render代替template
- 總結
- 回顧和復習已學的知識點
- 總結組件 渲染/更新過程
- 回顧學過的知識
- 組件 渲染/更新過程
- vue組件是如何渲染和更新的
- 初次渲染過程
- 執行render函數會觸發getter
- 更新過程
- 完成流程圖
- 異步渲染
- 總結1
- 總結2
- 如何用JS實現hash路由
- 前端路由原理
- hash的特點
- 如何用JS實現H5 history路由
- H5 history
- 正常頁面瀏覽
- 改造成H5 history模式
- 總結
- 兩者選擇
- vue原理-考點總結和復習
- 組件化
- 響應式
- vdom和diff
- 模板編譯
- 渲染過程
- 前端路由
Vue原理(大廠必考)
面試為何會考察原理
面試中如何考察?以何種方式
考察重點,而不是考察細節,掌握好2/8原則
和使用相關聯的原理,例如vdom、模板渲染
整體流程是否全面?熱門技術是否有深度?
Vue原理包括哪些?
組件化
響應式
vdom和diff
模板編譯
渲染過程
前端路由
如何理解MVVM
組件化基礎
“很久以前”就有組件化
asp jsp php已經有組件化了
nodejs中也有類似的組件化
數據驅動視圖(MVVM,setState)
傳統組件,只是靜態渲染,更新還要依賴于操作DOM
數據驅動視圖–Vue MVVM
數據驅動視圖–React setState(暫時先不看)
Vue MVVM
總結
組件化
數據驅動視圖
MVVM
監聽data變化的核心API是什么
Vue響應式
組件data的數據一旦變化,立刻觸發視圖的更新
實現數據驅動視圖的第一步
考察Vue原理的第一題
核心API-Object.defineProperty
如何實現響應式,代碼演示
Object.defineProperty的一些缺點(Vue3.0啟用Proxy)
Proxy有兼容性問題
Proxy兼容性不好,且無法polyfill
Vue2.x還會存在一段時間,所以都得學
Vue3.0相關知識,下一章將,這里只是先提一下
Object.defineProperty基本用法
Object.defineProperty實現響應式
監聽對象,監聽數組
復雜對象,深度監聽
幾個缺點
如何深度監聽data變化、數組變化
Object.defineProperty缺點
深度監聽,需要遞歸到底,一次性計算量大
無法監聽新增屬性/刪除屬性(Vue.set Vue.delete)
無法原生監聽數組,需要特殊處理
總結
基礎API-Object.defineProperty
如何監聽對象(深度監聽),監聽數組
Object.defineProperty的缺點
虛擬DOM-面試里的網紅
虛擬DOM(Virtual DOM)和diff
vdom是實現vue和React的重要基石
diff算法是vdom中最核心、最關鍵的部分
vdom是一個熱門話題,也是面試中的熱門話題
DOM操作非常耗費性能
以前用jQuery,可以自行控制DOM操作的時機,手動調整
Vue和React是數據驅動視圖,如何有效控制DOM操作?
解決方案-vdom
有了一定復雜度,想減少計算次數比較難
能不能把計算,更多的轉移為JS計算?因為JS執行速度很快
vdom-用JS模擬DOM結構,計算出最小的變更,操作DOM
通過snabbdom學習vdom
簡潔強大的vdom庫,易學易用
Vue參考它實現的vdom和diff
https://github.com/snabbdom/snabbdom
Vue3.0重寫了vdom的代碼,優化了性能
但vdom的基本理念不變,面試考點也不變
React vdom具體實現和Vue也不同,但不妨礙統一學習
用過虛擬DOM嗎?
snabbdom重點總結
h函數
vnode數據結構
patch函數
vdom總結
用JS模擬DOM結構(vnode)
新舊vnode對比,得出最小的更新范圍,最后更新DOM
數據驅動視圖的模式下,有效控制DOM操作
虛擬DOM-diff算法概述
diff算法是vdom中最核心、最關鍵的部分
diff算法能在日常使用vue React中體現出來(如key)
diff算法是前端熱門話題,面試“寵兒”
diff即對比,是一個廣泛的感念,如linux diff命令、git diff等
兩個js對象也可以做diff,如https://github.com/cujojs/jiff
兩棵樹做diff,如這里的vdom diff
樹diff的時間復雜度O(n^3)
第一,遍歷tree1;第二,遍歷tree2
第三,排序
1000個節點,要計算1億次,算法不可用
優化時間復雜度到O(n)
只比較同一層級,不跨級比較
tag不相同,則直接刪掉重建,不再深度比較
tag和key,兩者都相同,則認為是相同節點,不再深度比較
深入diff算法源碼
生成vnode
h函數
patch函數
執行pre hook
第一個參數不是vnode-創建一個空的vnode(emptyNodeAt),關聯到這個DOM元素
判斷vnode是否相同(sameVnode)-key和sel都相等
相同執行patchVnode
不相同,直接刪掉重建
patchVnode函數(vnode對比)
-
執行prepatch hook(生命周期的鉤子)
-
設置vnode.elem
-
vnode.text===undefined(vnode.children一般有值)
新舊都有children,updateChildren;新children有,舊children無(舊text有),清空text,添加children(addVnodes);舊children有,新children無,移除children(removeVnodes);舊text有,清空 -
vnode.text!==undefined(vnode.children一般無值)
新舊text不一樣,移除舊children,設置新text
updateChildren函數
- 開始和開始對比
patchVnode()
累加累減 - 結束和結束對比
patchVnode()
累加累減 - 開始和結束對比
patchVnode()
累加累減 - 結束和開始對比
patchVnode()
累加累減 - 以上四個都未命中
拿新節點key,能否對應上oldCh中的某個節點的key
沒對應上,New element
對應上,拿到對應上key的節點,判斷sel是否相等,不相等New element,相等patchVnode()
不使用key全部刪掉然后插入,使用key直接移動過來,不用做銷毀然后重新渲染的過程
虛擬DOM-考點總結和復習
diff算法總結
patchVnode
addVnodes removeVnodes
updateChildren(key的重要性)
vdom和diff-總結
細節不重要,updateChildren的過程也不重要,不要深究
vdom核心概念很重要:h、vnode、patch、diff、key等
vdom存在的價值更加重要:數據驅動視圖,控制DOM操作
模板編譯前置知識點-with語法
模板編譯
模板是vue開發中最常用的部分,即與使用相關聯的原理
它不是html,有指令、插值、JS表達式,到底是什么
面試不會直接問,但會通過“組件渲染和更新過程”考察
前置知識:JS的with語法
vue template complier將模板編譯為render函數
執行render函數生成vnode
with語法
改變{}內自由變量的查找規則,當做obj屬性來查找
如果找不到匹配的obj屬性,就會報錯
with要慎用,它打破了作用域規則,易讀性變差
vue模板被編譯成什么?
模板不是html,有指令、插值JS表達式,能實現判斷、循環
html是標簽語言,只有JS才能實現判斷、循環(圖靈完備的:能實現順序執行、判斷、循環)
因此,模板一定是轉換為某種JS代碼,即編譯模板
編譯模板
模板編譯為render函數,執行render函數返回vnode
基于vnode再執行patch和diff(后面會講)
使用webpack vue-loader,會在開發環境下編譯模板(重要)
vue組件中使用render代替template
講完模板編譯,再講這個render,就比較好理解了
在有些復雜情況中,不能用template,可以考慮用render
React一直都用render(沒有模板),和這里一樣
總結
with語法
模板到render函數,再到vnode,再到渲染和更新
vue組件可以用render代替template
回顧和復習已學的知識點
總結組件 渲染/更新過程
一個組件渲染到頁面,修改data觸發更新(數據驅動視圖)
其背后原理是什么,需要掌握哪些要點
考察對流程了解的全面程度
回顧學過的知識
響應式:監聽data屬性getter setter(包括數組)
模板編譯:模板到render函數,再到vnode
vdom:patch(elem,vnode)和patch(vnode,newVnode)
組件 渲染/更新過程
初次渲染過程
更新過程
異步渲染
vue組件是如何渲染和更新的
初次渲染過程
解析模板為render函數(或在開發環境已完成,vue-loader)
觸發響應式,監聽data屬性getter setter
執行render函數,生成vnode,patch(elem,vnode)
執行render函數會觸發getter
<p>{{message}}</p> <script> export default {data(){return {message:'hello',//會觸發getcity:'北京'//不會觸發get,因為模板沒用到,即和視圖沒關系}} } </script>更新過程
修改data,觸發setter(此前在getter中已被監聽)
重新執行render函數,生成newVnode
patch(vnode,newVnode)
完成流程圖
異步渲染
回顧$nextTick
匯總data的修改,一次性更新視圖
減少DOM操作次數,提高性能
總結1
渲染和響應式的關系
渲染和模板編譯的關系
渲染和vdom的關系
總結2
初次渲染過程
更新過程
異步渲染
如何用JS實現hash路由
前端路由原理
稍微復雜一點的SPA,都需要路由
vue-router也是vue全家桶的標配之一
屬于“和日常使用相關聯的原理”,面試常考
回顧vue-router的路由模式
hash
H5 history
hash的特點
hash變化會觸發網頁跳轉,即瀏覽器的前進、后退
hash變化不會刷新頁面,SPA必須的特點
hash永遠不會提交到server端(前端自生自滅)
如何用JS實現H5 history路由
H5 history
用url規范的路由,但跳轉不刷新頁面
history.pushState
window.onpopstate
正常頁面瀏覽
https://github.com/xxx 刷新頁面
https://github.com/xxx/yyy 刷新頁面
https://github.com/xxx/yyy/zzz 刷新頁面
改造成H5 history模式
https://github.com/xxx 刷新頁面
https://github.com/xxx/yyy 前端跳轉,不刷新頁面
https://github.com/xxx/yyy/zzz 前端跳轉,不刷新頁面
總結
hash–window.onhashchange
H5 history–history.pushState和window.onpopstate
H5 history需要后端支持
兩者選擇
to B的系統推薦用hash,簡單易用,對url規范不敏感
to C的系統,可以考慮選擇H5 history,但需要服務端支持
能選擇簡單的,就別用復雜的,要考慮成本和收益
vue原理-考點總結和復習
組件化
組件化的歷史
數據驅動視圖
MVVM
響應式
Object.defineProperty
監聽對象(深度),監聽數組
Object.defineProperty的缺點(Vue3用Proxy,后面會講)
vdom和diff
應用背景
vnode結構
snabbdom使用:vnode h patch
模板編譯
with語法
模板編譯為render函數
執行render函數生成vnode
渲染過程
初次渲染過程
更新過程
異步渲染
前端路由
hash
H5 history
兩者對比
總結
- 上一篇: 陌陌点点如何找已认证的
- 下一篇: (五)Vue 面试真题演练