snabbdom源碼粗讀

snabbdom

本文的snabbdom源碼分析採用的是0.54版本(即未用ts重寫前的最後一版)html

前期瞭解

snabbdom被用做vue的虛擬dom。本文的一個目的就是對於進入vue源碼預備。
本文大體講解,而不會徹底細化至代碼行數講解vue

文件(如下只指出須要閱讀的主要文件)

  • modules
  • helper
  • h.js
  • htmldomapi.js
  • is.js
  • snabbdom.js
  • thunk.js
  • vnode.js

vnode.js

說白了就是返回一個數據表示dom結構的數據對象node

h.js

則是對多重有子結構 text節點之類的數據對象進行在再處理
返回一個解析好的vnodegit

htmltoapi

一些dom操做的api封裝
結合到後面作vnode渲染到真實dom的操做
is.js 兩個工具函數 一個是是否爲數組 一個是是否爲基本類型 也就是數字string這些文本節點github

modules

裏面放的則是一些對應的數據結構上例如property attribute之類的輔助操做算法

  • attributes

裏面用來更新節點的屬性
基本的套路都是一個for in迭代 而後內部判斷patch 判斷是否須要更新亦或者是刪除 若是存在屬性的話 且不一樣確定是更新 若是新有了 舊的沒有就增長 新沒有了舊還有 對於一些屬性直接設置false 或者是賦空便可segmentfault

  • class.js

這裏也是一些利用classList作快速增長修改刪除節點上的class的操做
基本簡單的判斷就是這種套路api

  • datatset

設置節點屬性值數組

  • eventlistener

看源碼能夠發現 事件綁定這一步傳入的參數其實是被包裝的
利用函數封裝了一層handleevent
handleevent裏面其實是觸發invokeHandler
那麼從源碼能夠看出 實際上觸發dom節點的綁定事件其實是在觸發
綁定在上下文爲vnode的觸發器上。瀏覽器

props設置節點這個props是須要鍵值對的。通常自定義屬性值在這裏聲明好一些,設置checked selected由於內部有一個booleanarray 其實有綁定的話只是作
property可以從attribute中獲得同步;
attribute不會同步property上的值;

事件綁定源碼圖

style.js

模擬動畫幀 用requestAnimationFrame不兼容則用setTimeout
requestAnimationFrame的好處是它的刷新頻率會與瀏覽器一致
setTimeout則有時候可能出現丟失的狀況

內部封裝一個兩層的調用來使用,大概是兩幀的意思
若是沒有delayed或者remove直接更新style便可

設置節點被destory時候的style
設置刪除效果也就是調用自定義的remove鉤子函數。若是沒有的話就調用全局的

這些定義都是根據api閱讀結合源碼發現的
remove鉤子執行後纔會刪除樣式

snabbdom

這塊是在網上看的源碼解讀
由於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作一些模塊的初始化 還有全局鉤子的初始化

emptyNodeAt

傳入一個節點 而後對這個節點進行操做提取 轉換成vnode數據對象

createRmCb

// remove攔截器 style裏面說起的
// 對remove鉤子回調作減法而後才刪除節點

createElm

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的。

本文寫於2017年05月22日

撒花。thanks
若是有須要詳細代碼解析的朋友能夠聯繫我獲取。


一些link

相關文章
相關標籤/搜索