本文的snabbdom源碼分析採用的是0.54版本(即未用ts重寫前的最後一版)html
snabbdom被用做vue的虛擬dom。本文的一個目的就是對於進入vue源碼預備。
本文大體講解,而不會徹底細化至代碼行數講解vue
說白了就是返回一個數據表示dom結構的數據對象node
則是對多重有子結構 text節點之類的數據對象進行在再處理
返回一個解析好的vnodegit
一些dom操做的api封裝
結合到後面作vnode渲染到真實dom的操做
is.js 兩個工具函數 一個是是否爲數組 一個是是否爲基本類型 也就是數字string這些文本節點github
裏面放的則是一些對應的數據結構上例如property attribute之類的輔助操做算法
裏面用來更新節點的屬性
基本的套路都是一個for in迭代 而後內部判斷patch 判斷是否須要更新亦或者是刪除 若是存在屬性的話 且不一樣確定是更新 若是新有了 舊的沒有就增長 新沒有了舊還有 對於一些屬性直接設置false 或者是賦空便可segmentfault
這裏也是一些利用classList作快速增長修改刪除節點上的class的操做
基本簡單的判斷就是這種套路api
設置節點屬性值數組
看源碼能夠發現 事件綁定這一步傳入的參數其實是被包裝的
利用函數封裝了一層handleevent
handleevent裏面其實是觸發invokeHandler
那麼從源碼能夠看出 實際上觸發dom節點的綁定事件其實是在觸發
綁定在上下文爲vnode的觸發器上。瀏覽器
props設置節點這個props是須要鍵值對的。通常自定義屬性值在這裏聲明好一些,設置checked selected由於內部有一個booleanarray 其實有綁定的話只是作
property可以從attribute中獲得同步;
attribute不會同步property上的值;
模擬動畫幀 用requestAnimationFrame不兼容則用setTimeout
requestAnimationFrame的好處是它的刷新頻率會與瀏覽器一致
setTimeout則有時候可能出現丟失的狀況
內部封裝一個兩層的調用來使用,大概是兩幀的意思
若是沒有delayed或者remove直接更新style便可
設置節點被destory時候的style
設置刪除效果也就是調用自定義的remove鉤子函數。若是沒有的話就調用全局的
這些定義都是根據api閱讀結合源碼發現的
remove鉤子執行後纔會刪除樣式
這塊是在網上看的源碼解讀
由於diff算法應該是一個vitrual dom實現的重點了
createKeyToOldIdx 給舊節點設置key用於比對
// create => style,class,dataset,eventlistener,props,hero
// update => style,class,dataset,eventlistener,props,hero
// remove => style
// destory => eventlistener,style,hero
// pre => hero
// post => hero
這是一些鉤子函數的使用api吧
init作一些模塊的初始化 還有全局鉤子的初始化
傳入一個節點 而後對這個節點進行操做提取 轉換成vnode數據對象
// remove攔截器 style裏面說起的
// 對remove鉤子回調作減法而後才刪除節點
vnode映射真實節點
看到這裏的時候對insertedVnodeQueue很不懂 究竟要幹嗎
而後忽然想明白了。這個大概是inserted的鉤子吧- -
在每一次插入操做的時候都將節點insert
api.這類型方法能夠看出來是在調用對應modules的方法
由於開始的時候就導入進來了
插入節點操做的時候都須要加入insertedVnodeQueue
子節點有子元素 也就是children的時候遞歸調用循環子節點生成tree
對應着一些操做以後都要觸發鉤子函數。
之前並不清楚鉤子函數生命週期觸發原理,此次卻是見識了
invokeDestroyHook 手動觸發destroy鉤子 先觸發vnode的鉤子 在觸發全局鉤子 再遞歸觸發子節點的鉤子
removeVnodes remove操做 由於要使得remove鉤子觸發後才刪除節點
updateChildren patchVnode 最主要的diff算法
利用先後索引的方式
進行對兩樹的遍歷patch 複雜度是O(n)
由於比較都是在同層作比較對比patch
起點在patchVnode 而後patch過程updateChildren 而後調用updateChildrens
一個分段的僞遞歸
而當索引不生效 這個時候則採用傳統的key-index比對
網上的一些simple vitrual dom教程
實現的是基於深度遍歷作list diff
而後取得節點的變化
在作對應操做 。
snabbdom的patch等等 都是基於數據對象作的。
而一些vitrual的實現是基於樹的patch
virtual-dom的一個好處就是讓咱們能夠從繁雜無章的dom操做中解脫,利用js對象的形式映射到dom,從而操做js數據操做dom
所謂的性能其實仍是得看你怎麼用,大片的修改dom不見得virtual dom就有多好用。
打算也實現個simple dom 佔坑~~(固然在path diff算法上可能不存在優化了)(佔坑佔坑)
snabbdom也是vue使用的virtual dom 庫,emmm以後能夠看看vue是怎麼結合使用snabbdom的。
撒花。thanks
若是有須要詳細代碼解析的朋友能夠聯繫我獲取。