虛擬 DOM 結構概念隨着 react 的誕生而火起來,以後 vue2.0 也加入了虛擬 DOM 的概念。javascript
閱讀 vue 源碼的時候,想了解虛擬 dom 結構的實現,發如今 src/core/vdom/patch.js
的地方。做者說 vue 的虛擬 DOM 的算法是基於 snabbdom 進行改造的。html
因而 google 一下,發現 snabbdom 實現的十分優雅,代碼更易讀。 因此決定先去把 snabbdom 的源碼啃了以後,再回過頭來啃 vue 虛擬 DOM 這一塊的實現。前端
在前端刀耕火種的時代,jquery 可謂是一家獨大。然而慢慢的人們發現,在咱們的代碼中佈滿了一系列操做 DOM 的代碼。這些代碼難以維護,又容易出錯。並且也難以測試。vue
因此,react 利用了 Virtual DOM 簡化 dom 操做,讓數據與 dom 之間的關係更直觀更簡單。java
Virtual DOM 主要包括如下三個方面:node
下面開始來研究 snabbdom 是如何實現這些方面的react
項目路徑 : https://github.com/snabbdom/snabbdomjquery
首先看一下總體的目錄結構,源碼主要是在 src
裏面,其餘的目錄:test
、examples
分別是測試用例以及例子。git
這裏咱們先關注源碼部分github
── h.ts 建立vnode的函數 ── helpers └── attachto.ts ── hooks.ts 定義鉤子 ── htmldomapi.ts 操做dom的一些工具類 ── is.ts 判斷類型 ── modules 模塊 ├── attributes.ts ├── class.ts ├── dataset.ts ├── eventlisteners.ts ├── hero.ts ├── module.ts ├── props.ts └── style.ts ── snabbdom.bundle.ts 入口文件 ── snabbdom.ts 初始化函數 ── thunk.ts 分塊 ── tovnode.ts dom元素轉vnode ── vnode.ts 虛擬節點對象
snabbdom.bundle.ts
入口文件咱們先從入口文件開始看起
import { init } from './snabbdom'; import { attributesModule } from './modules/attributes'; // for setting attributes on DOM elements import { classModule } from './modules/class'; // makes it easy to toggle classes import { propsModule } from './modules/props'; // for setting properties on DOM elements import { styleModule } from './modules/style'; // handles styling on elements with support for animations import { eventListenersModule } from './modules/eventlisteners'; // attaches event listeners import { h } from './h'; // helper function for creating vnodes // 入口文件 // 初始化,傳入須要更新的模塊。 var patch = init([ // Init patch function with choosen modules attributesModule, classModule, propsModule, styleModule, eventListenersModule ]) as (oldVNode: any, vnode: any) => any; // 主要導出 snabbdomBundle , 主要包含兩個函數,一個是 修補函數 , 一個是 h 函數 export const snabbdomBundle = { patch, h: h as any }; export default snabbdomBundle;
咱們能夠看到,入口文件主要導出兩個函數 ,
patch
函數 , 由 snabbdom.ts
的 init
方法,根據傳入的 module
來初始化h
函數 ,在 h.ts
裏面實現。看起來 h
函數比 patch
要簡單一些,咱們去看看到底作了些什麼。