一、響應(yīng)式:


/*
*
* 根據(jù)上圖實現(xiàn)整體一個架構(gòu)(包括MVVM類或者Vue類- 發(fā)布者,Watcher類-訂閱者), 這里用到了一個訂閱發(fā)布者設(shè)計模式
*
* 然后實現(xiàn)MVVM中的由M->V,把模型里面的數(shù)據(jù)綁定到視圖
*
* 最后實現(xiàn)V->M, 當文本框輸入文本的時候,由文本事件觸發(fā)更新模型中的數(shù)據(jù),同時也更新相對應(yīng)的視圖
*
*/
實現(xiàn)數(shù)據(jù)驅(qū)動視圖的第一步, 組件data的數(shù)據(jù)一旦變化,立刻觸發(fā)視圖的更新
1、核心API --- Object.defineProperty : [作用就是直接在一個對象上定義一個新屬性,或者修改一個已經(jīng)存在的屬性]
2、Object.defineProperty(obj, prop, desc) 【 監(jiān)聽對象、數(shù)組; 復(fù)雜對象、深度監(jiān)聽】
2.1、obj 需要定義屬性的當前對象
2.2、prop 當前需要定義的屬性名
2.3、desc 屬性描述符
3、缺點(vue3.0啟用Proxy--兼容性不好,且無法polyfill):
3.1、深度監(jiān)聽, 需要遞歸到底,一次計算量比較大,性能不好
3.2、無法監(jiān)聽原生數(shù)組, 需要特殊處理 【需要重新定義數(shù)組原型】

3.3、不能監(jiān)聽對象新增或刪除屬性 --- Vue.set 和 Vue.delete
二、模版編譯 -- complier 【返回Vnode】
template -----》render過程
模版 ----》 真實DOM渲染的過程,中間有一個環(huán)節(jié)是把模板編譯成 render 函數(shù),這個過程我們把它稱作編譯。
Vue.js 提供了 2 個版本:
1、 Runtime + Compiler : 含編譯代碼的,可以把編譯過程放在運行時做
2、Runtime only : 需要借助 webpack 的 vue-loader 事先把模板編譯成 render函數(shù)

首先從[$mount]開始,可以看到,mount其實就是拿到了模板template,然后將這個template通過compileToFunctions方法編譯成render函數(shù), 主要是調(diào)用了compileToFunctions里面的compile方法。
const compiled = compile(template, options)

parse: 主要功能是將 template字符串解析成 AST(抽象語法樹)--- 解釋器;
optimize: 主要功能標記靜態(tài)節(jié)點,為后面 patch 過程中對比新舊 VNode 樹形結(jié)構(gòu)做優(yōu)化 --- 優(yōu)化器 ;
generate: 主要功能就是根據(jù) AST 結(jié)構(gòu)拼接生成 render 函數(shù)的字符串 --- 生成器,如下:
{render: "with(this){return _c('div',{attrs:{"id":"test"}},[[_v(_s(val))]),_v(" "),_m(0)])}"}
后面通過 new Function 得到真正的渲染函數(shù)
render ----> VNode
關(guān)鍵: 主要通過 createElement 創(chuàng)建VNode

三、虛擬DOM & diff算法 -- vdom庫 - snabbdom
【VNode 節(jié)點的形式來模擬一棵 Virtual DOM】
**虛擬DOM **
它產(chǎn)生的前提是瀏覽器中的 DOM 是很“昂貴"的,當我們頻繁的去做 DOM 更新,會產(chǎn)生一定的性能問題

理解: 用JS模擬DOM結(jié)構(gòu), 計算出最小的變更,操作DOM。

snabbdom源碼代碼:

總結(jié):
1、用JS模擬DOM結(jié)構(gòu)(vnode)
2、新舊vnode對比,得出最小的更新范圍,最后更新DOM ----- diff算法
3、數(shù)據(jù)驅(qū)動視圖模式下,有效控制DOM操作
diff算法
【diff 算法是vdom中最核心、最關(guān)鍵的部分, 是實現(xiàn)Vue 和 React的重要基石】
【diff算法能在日常使用Vue React中體現(xiàn)出來 (key)】
- diff 即對比, 是一個比較廣泛的概念,如 linux diff命令、git diff、文件對比器等等。
- 兩個js對象也可以做diff
- 兩棵樹做diff, 如這里的VDOM diff

優(yōu)化時間復(fù)雜度到 O(n)
1、之比較同一層級,不跨級比較
2、tag不相同, 則直接刪掉重建, 不在深度比較
3、tag 和 key兩者都相同,則認為是相同節(jié)點, 不再深度比較

關(guān)鍵函數(shù): patch()、patchVnode()、addVnodes、removeVnodes、updataChildren()【兩種情況下都有children 對比 key的重要性】
四、組件化

