JS每日一題:Vue中的diff算法?

20190125

Vue中的diff算法?vue

概念: diff算法是一種優化手段,將先後兩個模塊進行差別對比,修補(更新)差別的過程叫作patch(打補丁)

爲何vue,react這些框架中都會有diff算法呢? 咱們都知道渲染真實dom的開銷是很大的,這個跟性能優化中的重繪重排意義相似, 回到正題來, 有時候咱們修改了頁面中的某個數據,若是直接渲染到真實DOM中會引發整棵數的重繪重排, 那麼咱們能不能只讓咱們修改的數據映射到真實DOM, 作一個最少化重繪重排呢,說到這裏你應該對爲何使用diff算法有一個簡單的概念了node

virtual DOM和真實DOM的區別

一句話歸納吧,virtual DOM是將真實的DOM的數據抽取出來,以對象的形式模擬樹形結構, diff 算法比較的也是virtual DOMreact

代碼理解git

<div>
    <p>JS每日一題</p>
</div>

// 轉換成VNode 相似於下面這種

const Vnode = {
    tag: 'div',
    children: [
        { tag: 'p', text: 'JS每日一題' }
    ]
};
diff 是如何比較的?
源碼太多了,就不貼了, 有興趣的能夠本身看看 https://github.com/vuejs/vue/...

簡單的說就是新舊虛擬dom 的比較,若是有差別就以新的爲準,而後再插入的真實的dom中,從新渲染github

特色算法

  • 只會作同級比較,不作跨級比較
  • 比較後幾種狀況性能優化

    • if (oldVnode === vnode),他們的引用一致,能夠認爲沒有變化。
    • if(oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text),文本節點的比較,須要修改,則會調用Node.textContent = vnode.text
    • if( oldCh && ch && oldCh !== ch ), 兩個節點都有子節點,並且它們不同,這樣咱們會調用updateChildren函數比較子節點,這是diff的核心
    • else if (ch),只有新的節點有子節點,調用createEle(vnode)vnode.el已經引用了老的dom節點,createEle函數會在老dom節點上添加子節點。
    • else if (oldCh),新節點沒有子節點,老節點有子節點,直接刪除老節點。
key的做用

設置key和不設置key的區別:
不設key,newCh和oldCh只會進行頭尾兩端的相互比較,設key後,除了頭尾兩端的比較外,還會從用key生成的對象oldKeyToIdx中查找匹配的節點,因此爲節點設置key能夠更高效的利用dom框架

如咱們但願能夠在B和C之間加一個F,Diff算法默認執行起來是這樣的:dom

即把C更新成F,D更新成C,E更新成D,最後再插入E,是否是很沒有效率?函數

因此咱們須要使用key來給每一個節點作一個惟一標識,Diff算法就能夠正確的識別此節點,找到正確的位置區插入新的節點。



因此一句話,key的做用主要是爲了高效的更新虛擬DOM。另外vue中在使用相同標籤名元素的過渡切換時,也會使用到key屬性,其目的也是爲了讓vue能夠區分它們,不然vue只會替換其內部屬性而不會觸發過渡效果

總結

  • 儘可能不要跨層級的修改dom
  • 在開發組件時,保持穩定的 DOM 結構會有助於性能的提高
  • 設置key可讓diff更高效

關於JS每日一題

JS每日一題能夠當作是一個語音答題社區
天天利用碎片時間採用60秒內的語音形式來完成當天的考題
羣主在第二天0點推送當天的參考答案

  • 注 毫不僅限於完成當天任務,更可能是查漏補缺,學習羣內其它同窗優秀的答題思路

點擊加入答題

相關文章
相關標籤/搜索