從vue源碼角度分析key的做用

在文檔中說到:html

  • key 的特殊 attribute 主要用在 Vue 的虛擬 DOM 算法,在新舊 nodes 對比時辨識 VNodes
  • 若是不使用 key,Vue 會使用一種最大限度減小動態元素而且儘量的嘗試就地修改/複用相同類型元素的算法。
  • 而使用 key 時,它會基於 key 的變化從新排列元素順序,而且會移除/銷燬 key 不存在的元素。

在分析以前須要簡單瞭解倆個概念 Vnode虛擬DOMvue

須要瞭解的倆個概念

Vnode

Vnode 全稱爲 Virtual Node, 即 虛擬節點 ,而它的本質就是一個JS對象node

以代碼爲例:web

<div class="text" style="font-size: 26px;color: pink">這是一段文本內容</div>
複製代碼

// vue 會把 模板中的內容 轉換爲 vNode(對象)算法

const vNode = {
  type: 'div',
  props: {
    class: 'text',
    style: {
      'font-size': '26px',
      color: 'pink'
    },
  },
  children:'這是一段文本內容'
};
複製代碼

虛擬DOM

文檔中說到:api

  • 虛擬 DOM 是輕量級的 JavaScript 對象,由渲染函數建立。
  • 它包含三個參數:元素,具備數據、prop、attr 等的對象,以及一個數組。
  • 數組是咱們傳遞子級的地方,子級也具備全部這些參數,而後它們也能夠具備子級,依此類推,直到咱們構建完整的元素樹爲止。

以代碼爲例:數組

<div>
  <h1>標題</h1>
  這是一段文本內容
  <!-- 這是註釋 -->
</div>
複製代碼

// 轉換爲虛擬DOMmarkdown

image.png

插入內容的案例

先看一個案例:當咱們點擊按鈕時會插入一個數字5進去:svg

image.png

在整個過程當中,咱們能夠肯定的是vue在內部此次更新對於ul和button是不須要進行更新,須要更新的是li的列表。函數

在Vue中,對於相同父元素的子元素節點並不會從新渲染整個列表;由於對於列表中 一、二、三、4 它們都是沒有變化的。在操做真實DOM的時候,咱們只須要在中間插入一個5的li便可。

那麼Vue中對於列表的更新到底是如何操做的呢?

Vue事實上會對於有key和沒有key會調用兩個不一樣的方法:

  1. 有key,那麼就使用 patchKeyedChildren 方法;
  2. 沒有key,那麼久使用 patchUnkeyedChildren 方法;

Vue3源碼對於Key的判斷

image.png

沒有key的操做狀況下,vue源碼的作法

在沒有key的狀況下,vue3源碼是經過 patchUnkeyedChildren 方法來實現的

具體實現如圖下:

第一步:遍歷循環經過patch方法來作比較 image.png 第二步和第三步:判斷新舊nodes的長度來進行對節點的刪除或者新增 image.png

在有key的狀況下,vue源碼的作法

有key的狀況下,vue對其操做有點複雜,可分爲 5 個步驟。

具體以下圖所示:

第一步:

image.png

第二步:

image.png

第三步:

image.png

第四步:

image.png

第五步:

image.png

總結

咱們能夠發現,Vue在進行diff算法的時候,會盡可能利用咱們的key來進行優化操做,全部在沒有key的狀況下咱們的效率是很是低的。 在進行插入或者重置排序的時候,保持相同的key可讓diff算法更加高效。

相關文章
相關標籤/搜索