zishu's blog

zishu's blog

一个热爱生活的博主。https://zishu.me

為什麼 key 是必須的?

之前有說到,在 React 中渲染列表的時候,要給每一個資料加一個 key 值,賦予一個確定的標示,而且也詳細描述了如何給一個標示,方法知道了,那麼為什麼要這麼做呢?

在 React 中如何渲染列表?

在預設條件下,當遞迴 DOM 節點的子元素時,React 會同時遍歷兩個子元素的列表;當產生差異時,生成一個 mutation。

在子元素列表末尾新增元素時,更新開銷比較小。比如:

<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

React 會先匹配兩個 <li>first</li> 對應的樹,然後匹配第二個元素 <li>second</li> 對應的樹,最後插入第三個元素的 <li>third</li> 樹。

如果只是簡單的將新增元素插入到表頭,那麼更新開銷會比較大。比如:

<ul>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

<ul>
  <li>Connecticut</li>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

React 不會意識到應該保留 <li>Duke</li><li>Villanova</li>,而是會重建每一個子元素 。這種情況會帶來性能問題。

key

為了解決上述問題, React 支援 key 屬性,當子元素擁有 key 時,React 使用 key 來匹配原有樹上的子元素以及最新樹上的子元素。以下例子在新增 key 之後使得之前的低效轉換變得高效:

<ul>
  <li key="1">Duke</li>
  <li key="2">Villanova</li>
</ul>

<ul>
  <li key="0">Connecticut</li>
  <li key="1">Duke</li>
  <li key="2">Villanova</li>
</ul>

現在 React 知道只有帶著 '0' key 的元素是新元素,帶著 '1' 以及 '2' key 的元素僅僅移動了。

現實場景中,產生一個 key 並不困難。你要展現的元素可能已經有了一個唯一 ID,於是 key 可以直接從你的資料中提取:

<li key={item.id}>{item.name}</li>

當以上情況不成立時,你可以新增一個 ID 欄位到你的模型中,或者利用一部分內容作為哈希值來生成一個 key。這個 key 不需要全域唯一,但在列表中需要保持唯一。

最後,你也可以使用元素在陣列中的下標作為 key。這個策略在元素不進行重新排序時比較合適,如果有順序修改,diff 就會變得慢。

當基於下標的元件進行重新排序時,元件 state 可能會遇到一些問題。由於元件實例是基於它們的 key 來決定是否更新以及複用,如果 key 是一個下標,那麼修改順序時會修改當前的 key,導致非受控元件的 state(比如輸入框)可能相互篡改導致無法預期的變動。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。