(三)Vue-Snabbdom

虛擬 DOM 的作用

  1. 維護視圖和狀態(tài)的關系
  2. 復雜視圖情況下提升渲染性能
  3. 跨平臺
    ? 瀏覽器平臺渲染DOM
    ? 服務端渲染 SSR(Nuxt.js/Next.js)
    ? 原生應用(Weex/React Native)
    ? 小程序(mpvue/uni-app)等

Snabbdom

  1. Vue.js 2.x 內(nèi)部使用的虛擬 DOM 就是改造的 Snabbdom ?
  2. 大約 200 SLOC (single line of code) 3
  3. 通過模塊可擴展
  4. 源碼使用 TypeScript 開發(fā) ?
  5. 最快的 Virtual DOM 之一

導入 Snabbdom

  1. 安裝 Snabbdom
    ? npm intall snabbdom@2.1.0
  2. 導入 Snabbdom
    Snabbdom 的兩個核心函數(shù) init 和 h()
    ? init() 是一個高階函數(shù)腔剂,返回 patch()
    ? h() 返回虛擬節(jié)點 VNode射沟,這個函數(shù)我們在使用 Vue.js 的時候見過
  3. 文檔中導入的方式


  4. 實際導入的方式
    parcel/webpack 4 不支持 package.json 中的 exports 字段


模塊

模塊的作用
  1. Snabbdom 的核心庫并不能處理 DOM 元素的屬性/樣式/事件等操骡, 可以通過注冊 Snabbdom 默認提供的模塊來實現(xiàn)
  2. Snabbdom 中的模塊可以用來擴展 Snabbdom的功能
  3. Snabbdom 中的模塊的實現(xiàn)是通過注冊全局的鉤子函數(shù)來實現(xiàn)的
官方提供的模塊

?attributes
? props
? dataset
? class
? style
? eventlisteners

  1. 導入需要的模塊
  2. init() 中注冊模塊
  3. h() 函數(shù)的第二個參數(shù)處使用模塊

Snabbdom 的核心

  1. init() 設置模塊钉稍,創(chuàng)建 patch() 函數(shù)
  2. 使用 h() 函數(shù)創(chuàng)建 JavaScript 對象(VNode)描述真實 DOM
  3. patch() 比較新舊兩個 Vnode
  4. 把變化的內(nèi)容更新到真實 DOM 樹

patch 整體過程分析

? patch(oldVnode, newVnode)
? 把新節(jié)點中變化的內(nèi)容渲染到真實 DOM,最后返回新節(jié)點作為下一次 處理的舊節(jié)點
? 對比新舊 VNode 是否相同節(jié)點(節(jié)點的 key 和 sel 相同)
? 如果不是相同節(jié)點四敞,刪除之前的內(nèi)容啥纸,重新渲染
? 如果是相同節(jié)點究珊,再判斷新的 VNode 是否有 text,如果有并且和 oldVnode 的 text 不同竿裂,直接更新文本內(nèi)容
? 如果新的 VNode 有 children玉吁,判斷子節(jié)點是否有變化

Diff 算法

Snbbdom 根據(jù) DOM 的特點對傳統(tǒng)的diff算法做了優(yōu)化
? DOM 操作時候很少會跨級別操作節(jié)點
? 只比較同級別的節(jié)點


執(zhí)行過程

在對開始和結束節(jié)點比較的時候,總共有四種情況
? oldStartVnode / newStartVnode (舊開始節(jié)點 / 新開始節(jié)點)
? oldEndVnode / newEndVnode (舊結束節(jié)點 / 新結束節(jié)點)
? oldStartVnode / newEndVnode (舊開始節(jié)點 / 新結束節(jié)點)
? oldEndVnode / newStartVnode (舊結束節(jié)點 / 新開始節(jié)點)


開始和結束節(jié)點

如果新舊開始節(jié)點是 sameVnode (key 和 sel 相同)
? 調(diào)用 patchVnode() 對比和更新節(jié)點
? 把舊開始和新開始索引往后移動 oldStartIdx++ / newStartIdx++


舊開始節(jié)點 / 新結束節(jié)點

? 調(diào)用 patchVnode() 對比和更新節(jié)點
? 把 oldStartVnode 對應的 DOM 元素腻异,移動到右邊进副,更新索引
為什么要移動到右邊?

舊結束節(jié)點 / 新開始節(jié)點

? 調(diào)用 patchVnode() 對比和更新節(jié)點
? 把 oldEndVnode 對應的 DOM 元素悔常,移動到左邊影斑,更新索引
為什么要移動到左邊?

非上述四種情況
  1. 遍歷新節(jié)點机打,使用 newStartNode 的 key 在老節(jié)點數(shù)組中找相同節(jié)點
  2. 如果沒有找到矫户,說明 newStartNode 是新節(jié)點
    ? 創(chuàng)建新節(jié)點對應的 DOM 元素,插入到 DOM 樹中
  3. 如果找到了
    ? 判斷新節(jié)點和找到的老節(jié)點的 sel 選擇器是否相同
    ? 如果不相同残邀,說明節(jié)點被修改了
    重新創(chuàng)建對應的 DOM 元素皆辽,插入到 DOM 樹中
    ? 如果相同柑蛇,把 elmToMove 對應的 DOM 元素,移動到左邊


循環(huán)結束

? 當老節(jié)點的所有子節(jié)點先遍歷完 (oldStartIdx > oldEndIdx)驱闷,循環(huán)結束
? 新節(jié)點的所有子節(jié)點先遍歷完 (newStartIdx > newEndIdx)耻台,循環(huán)結束

  1. oldStartIdx > oldEndIdx
    如果老節(jié)點的數(shù)組先遍歷完(oldStartIdx > oldEndIdx)
    ? 說明新節(jié)點有剩余,把剩余節(jié)點批量插入到右邊


  2. newStartIdx > newEndIdx
    如果新節(jié)點的數(shù)組先遍歷完(newStartIdx > newEndIdx)
    ? 說明老節(jié)點有剩余空另,把剩余節(jié)點批量刪除


最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盆耽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子扼菠,更是在濱河造成了極大的恐慌征字,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娇豫,死亡現(xiàn)場離奇詭異匙姜,居然都是意外死亡,警方通過查閱死者的電腦和手機冯痢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門氮昧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浦楣,你說我怎么就攤上這事袖肥。” “怎么了振劳?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵椎组,是天一觀的道長。 經(jīng)常有香客問我历恐,道長寸癌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任弱贼,我火速辦了婚禮蒸苇,結果婚禮上,老公的妹妹穿的比我還像新娘吮旅。我一直安慰自己溪烤,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布庇勃。 她就那樣靜靜地躺著檬嘀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪责嚷。 梳的紋絲不亂的頭發(fā)上鸳兽,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音再层,去河邊找鬼贸铜。 笑死堡纬,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蒿秦。 我是一名探鬼主播烤镐,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼棍鳖!你這毒婦竟也來了炮叶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤渡处,失蹤者是張志新(化名)和其女友劉穎镜悉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體医瘫,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡侣肄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了醇份。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稼锅。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖僚纷,靈堂內(nèi)的尸體忽然破棺而出矩距,到底是詐尸還是另有隱情,我是刑警寧澤怖竭,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布锥债,位于F島的核電站,受9級特大地震影響痊臭,放射性物質(zhì)發(fā)生泄漏哮肚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一趣兄、第九天 我趴在偏房一處隱蔽的房頂上張望绽左。 院中可真熱鬧,春花似錦艇潭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至总棵,卻和暖如春鳍寂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背情龄。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工迄汛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捍壤,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓鞍爱,卻偏偏與公主長得像鹃觉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子睹逃,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容