JS每日一题:Vue中的diff算法?
20190125
Vue中的diff算法?
概念: diff算法是一種優化手段,將前后兩個模塊進行差異對比,修補(更新)差異的過程叫做patch(打補丁)為什么vue,react這些框架中都會有diff算法呢? 我們都知道渲染真實dom的開銷是很大的,這個跟性能優化中的重繪重排意義類似, 回到正題來, 有時候我們修改了頁面中的某個數據,如果直接渲染到真實DOM中會引起整棵數的重繪重排, 那么我們能不能只讓我們修改的數據映射到真實DOM, 做一個最少化重繪重排呢,說到這里你應該對為什么使用diff算法有一個簡單的概念了
virtual DOM和真實DOM的區別
一句話概括吧,virtual DOM是將真實的DOM的數據抽取出來,以對象的形式模擬樹形結構, diff 算法比較的也是virtual DOM
代碼理解
<div><p>JS每日一題</p> </div>// 轉換成VNode 類似于下面這種const Vnode = {tag: 'div',children: [{ tag: 'p', text: 'JS每日一題' }] };diff 是如何比較的?
源碼太多了,就不貼了, 有興趣的可以自己看看 https://github.com/vuejs/vue/...簡單的說就是新舊虛擬dom 的比較,如果有差異就以新的為準,然后再插入的真實的dom中,重新渲染
特點
- 只會做同級比較,不做跨級比較
-
比較后幾種情況
- 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算法默認執行起來是這樣的:
即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很沒有效率?
所以我們需要使用key來給每個節點做一個唯一標識,Diff算法就可以正確的識別此節點,找到正確的位置區插入新的節點。
所以一句話,key的作用主要是為了高效的更新虛擬DOM。另外vue中在使用相同標簽名元素的過渡切換時,也會使用到key屬性,其目的也是為了讓vue可以區分它們,否則vue只會替換其內部屬性而不會觸發過渡效果
總結
- 盡量不要跨層級的修改dom
- 在開發組件時,保持穩定的 DOM 結構會有助于性能的提升
- 設置key可以讓diff更高效
關于JS每日一題
JS每日一題可以看成是一個語音答題社區
每天利用碎片時間采用60秒內的語音形式來完成當天的考題
群主在次日0點推送當天的參考答案
- 注 絕不僅限于完成當天任務,更多是查漏補缺,學習群內其它同學優秀的答題思路
點擊加入答題
總結
以上是生活随笔為你收集整理的JS每日一题:Vue中的diff算法?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: roncoo-pay 开源支付系统全新架
- 下一篇: 从身份管理系统思考企业CMDB的建设