Vue.js 源碼剖析-響應(yīng)式原理、虛擬 DOM、模板編譯和組件化
簡答題
1、請(qǐng)簡述 Vue 首次渲染的過程。
- new Vue() 創(chuàng)建 Vue 實(shí)例
- 調(diào)用 this._init() 方法
- 合并 options 初始化 options 中的屬性
- 觸發(fā) beforeCreate 和 created 生命周期鉤子函數(shù)
- 調(diào)用 vm.$mount()
- 判斷是否有傳入 render(h 函數(shù)),如果沒有傳入 render,就調(diào)用 complierToFunctions()將傳入的 template 模板轉(zhuǎn)為 render(完整版本才有的功能)
- 如果有傳入 render,直接調(diào)用 mountComponent()
- mountComponent()
- 觸發(fā) beforeMounted 鉤子
- 定義 updateComponent
(1).vm.update()更新時(shí)觸發(fā),將虛擬 dom 轉(zhuǎn)為真實(shí) dom
(2).vm._render()渲染虛擬 DOM - 創(chuàng)建 Watcher 實(shí)例
- 觸發(fā) mounted
- return vm
- 調(diào)用 watcher.get()
- 創(chuàng)建完 watcher 會(huì)調(diào)用一次
- 調(diào)用 updateComponent()
- 調(diào)用 vm._render()創(chuàng)建 VNode
- 調(diào)用 vm._update()掛載真實(shí) DOM
2、請(qǐng)簡述 Vue 響應(yīng)式原理。
Vue2.x 中響應(yīng)式原理的核心是通過 Object.defineProperty 來挾持 data 中的屬性,在屬性被訪問時(shí) 調(diào)用 get 方法, 當(dāng)屬性被重新賦值時(shí)調(diào)用 set 方法來實(shí)現(xiàn)的具體實(shí)現(xiàn)如下:
- 遍歷$data 中的所有屬性,將其轉(zhuǎn)化為 getter 和 setter 注入到 Vue 實(shí)例中
- 利用 Observer 循環(huán)遍歷 data 中的每一個(gè)屬性成員,當(dāng)屬性被訪問時(shí),調(diào)用 dep 中的 addSub 收集依賴,當(dāng)屬性值發(fā)生改變時(shí)就會(huì)調(diào)用 dep 中的 notify 發(fā)送通知,通知 watcher 更新視圖
(需要判斷對(duì)象和數(shù)組,上面的方法適用于對(duì)象,數(shù)組只會(huì)將數(shù)組的值處理為響應(yīng)式的,不會(huì)循環(huán)里面的屬性) - 調(diào)用 Compiler()對(duì)象處理插值表達(dá)式,在處理差值表達(dá)式的過程中會(huì)創(chuàng)建 Watcher 實(shí)例,添加 target 屬性(Observer 中收集依賴只會(huì)收集含有 target 屬性的成員,如果沒有 target 屬性,說明頁面中沒有引用,無需收集)
3、請(qǐng)簡述虛擬 DOM 中 Key 的作用和好處。
- 作用:
當(dāng)虛擬 DOM 中的新老節(jié)點(diǎn)后含有子節(jié)點(diǎn)且不相同時(shí)會(huì)利用 diff 算法來比較子節(jié)點(diǎn)的差異
如果新老節(jié)點(diǎn)的開始節(jié)點(diǎn)和結(jié)束節(jié)點(diǎn)都不相同的話,需要用新節(jié)點(diǎn)的開始節(jié)點(diǎn)和結(jié)束節(jié)點(diǎn)去老節(jié)點(diǎn)中尋找具有相同 key 的節(jié)點(diǎn),從而減少 dom 的操作,如果此時(shí)沒有 key 的話就會(huì)直接更新老節(jié)點(diǎn) - 好處:
增加節(jié)點(diǎn)的重用性,避免節(jié)點(diǎn)頻繁的重繪,提升性能
避免出現(xiàn)順序錯(cuò)亂或者老節(jié)點(diǎn)中的其他屬性值被移動(dòng)到新節(jié)點(diǎn)中的問題
4、請(qǐng)簡述 Vue 中模板編譯的過程。
- 解析器(parse)
通過 parse 把 template 模板字符串轉(zhuǎn)為 AST 樹,它是一種用 JavaScript 隊(duì)形的形式來描述整個(gè)模板,整個(gè) parse 的過程是利用正則表達(dá)式順序解析模板,當(dāng)解析到開始標(biāo)簽、閉合標(biāo)簽、文本的時(shí)候都會(huì)分別執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù),來達(dá)到構(gòu)造 AST 樹的目的 - 優(yōu)化器(optimize)
通過 optimize 把整個(gè) AST 樹中的每一個(gè) AST 元素節(jié)點(diǎn)標(biāo)記了 static 和 staticRoot。optimize 的過程就是深度遍歷這個(gè) AST 樹,去檢測它的每一顆子樹是不是靜態(tài)節(jié)點(diǎn),如果是靜態(tài)節(jié)點(diǎn)則他們聲稱 DOM 永遠(yuǎn)不需要改變 - 代碼生成器(generate)
把優(yōu)化后的 AST 樹轉(zhuǎn)換成 render 函數(shù)的字符串