Vue v-for的key值如何設置?


Vue-for的key值到怎么設置?

在Vue項目中,v-for所在的DOM上,如果不設置key值,編輯器會警告;如果開啟了eslint,eslint檢查會提示需要給v-for設置key值 。我在做代碼CR時,發現很多同學喜歡設置key值為唯一標識,像以下代碼第二行設置為item.id。可能你也試過設置:key="index"也沒有問題。那么Vue的v-for key值到底怎么設置?

<div v-for="item in list"></div> <div v-for="item in list" :key="item.id"></div> <div v-for="(item,index) in list" :key="index"></div> 復制代碼

當我不設置key時

上代碼!

<div id="app">  <ul>    <li v-for="item in list">      <span>{{item.name}}</span>      <input type="text" />    </li>  </ul>  <button @click="exchange">交換</button> </div> <script>  const app = new Vue({    el: "#app",    data: {      list: [       {          id: 111,          name: "楊倩",       },       {          id: 222,          name: "楊皓然",       },     ],   },    methods: {      exchange() {        this.list.reverse();     },   }, }); </script> 復制代碼

list數組有兩對象,渲染成兩行,每一行包括name和一個輸入框;另外有一個“交換”按鈕,點擊會交換數組兩個對象。

以下圖片分別為“交換”前后。可以看到當數組元素交換時,界面元素也交換了。

image.png

image.png

有沒有DOM交換

我們使用Vue盡量不要操作DOM,因為Vue代替我們操作DOM。那么當數組元素交換時,Vue是如何操作DOM,進而交換界面元素呢?兩種方式:

  1. DOM交換
  2. DOM不交換,更新DOM的值

image.png

所以究竟有沒有DOM交換? 如果DOM不交換,更新DOM的值的話,只需要更新兩個span標簽的值,而input是無須交換的。這樣我們在輸入框中分別輸入1,2,再點擊“交換”按鈕,觀察到:

image.png

image.png

input標簽的值並沒有變,也就是並沒有交換liDOM !

想進一步證明,你也可以用js獲取li所在的dom元素,交換后,再重新獲取,用===對比。測試結果一樣,並沒有交換DOM

v-for key設置為index

我們再修改代碼,把v-for key值設置為index,觀察下是否會交換DOM

<li v-for="(item,index) in list" :key="index"> <span>{{item.name}}</span> <input type="text" /> </li> 復制代碼

觀察到交換前后和上面情況一致,input輸入框的值也沒有交換,也就是說並沒有交換DOM

v-for key設置為唯一標識

我們再修改代碼,把v-for key值設置為item.id,觀察下是否會交換DOM

<li v-for="item in list" :key="item.id"> <span>{{item.name}}</span> <input type="text" /> </li> 復制代碼

image.png

交換前后input輸入框的值也交換了,也就是說數組元素交換,對應渲染的DOM也交換了!

分析原因

v-for的key值三種設置方式,只有設置為唯一標識時,DOM才交換,為什么呢?很簡單,因為DOM交換耗性能,而Vue懶! 如果Demo沒有input框,交換數組元素時,需要交換name,那么交換DOM和不交換DOM方式都是正確的。 當 Vue 正在更新使用 v-for 渲染的元素列表時,它默認使用“就地更新”的策略,Vue官方文檔鏈接

解釋以上三種key值設置

  1. 不設置key值。默認使用“就地更新”,數組元素更新,更新對應的DOM的值。

2.設置key值為index。設置key值,Vue能區分已渲染的DOM,但是數組交換后改變了兩個元素各自的下標。所以原下標為1的元素,變成下標為0的元素,渲染原下標為0的DOM,無須交換DOM。 3.設置Key為item.id。item.id是唯一標識,Vue能區分已經渲染的DOM,元素交換后,DOM也會交換。

vfor的key設置為唯一標識效率高?!!

如果是的話,vfor內部實現時,怎么不直接設置key=Date.now(),即默認唯一標識。如果Vue源碼沒有實現,我們在寫一個指令替換vfor即可。所以之所以Vue源碼默認不設置vfor的key值為唯一標識,就是因為大多數情況下,就地更新效率更高!!! 我們使用v-for的大多數場景是這樣: 聲明data屬性為空數組,請求賦值,在結構中使用vfor渲染;再多一點邏輯就是更新數組元素的某一項和在給數組末尾新增一項。 想象一下以上場景中,Vue是如何進行DOM操作的。賦值就新增DOM元素,數組增加元素也是新增DOM元素,如果某元素更新呢?數組元素下標和已經渲染的DOM下標一致,找到然后更新值即可!

<div id="app"> <!-- 在結構中使用vfor渲染list --> <div v-for="item in items" :key="item.id"> {{ item }} </div> </div> <script> const app = new Vue({ el: "#app", data: { list: [], }, created(){ // 請求獲取數據,賦值給list this.list = this.$request(...) } }); </script> 復制代碼

當然如果是給數組中間插入一個元素,key值為唯一標識的確效率高些。這個和虛擬DOM有關,中文技術的世界這塊資料已經泛濫泛濫,大家自行查找。這可能也是常見代碼里面key值設置為唯一標識的原因。

 

結論

關於v-for的key值設置

  1. 如果已渲染的列表元素下標不會有變化,key值設置為index即可(防止eslint警告)
  2. 如果已渲染的列表元素下標會有變化,key值請設置為唯一標識
    • diff算法默認使用“就地復用”的策略,是一個首尾交叉對比的過程。
    • 用index作為key和不加key是一樣的,都采用“就地復用”的策略
    • “就地復用”的策略,只適用於不依賴子組件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸出。
    • 將與元素唯一對應的值作為key,可以最大化利用dom節點,提升性能


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM