欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue中key使用的問題示例解析

 更新時間:2022年11月28日 15:47:12   作者:空山與新雨  
這篇文章主要為大家介紹了vue中key使用的問題示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

在vue要求在遍歷的時候最好加上key,在使用過程中總有些疑問,在這里做下分析

不使用key的時候vue是怎么處理的

在vue2.x文檔中有如下描述

key 的特殊 attribute 主要用在 Vue 的虛擬 DOM 算法,在新舊 nodes 對比時辨識 VNodes。如果不使用 key,Vue 會使用一種最大限度減少動態(tài)元素并且盡可能的嘗試就地修改/復(fù)用相同類型元素的算法。而使用 key 時,它會基于 key 的變化重新排列元素順序,并且會移除 key 不存在的元素。

在這段話中提到不使用key的時候,會盡量原地復(fù)用,復(fù)用的判斷依據(jù)是常常在面試中被問到的sameVnode這個方法:

function sameVnode (a, b) {
  return (
    // 因?yàn)闆]有定義key,可以得知a.key和b.key都是undefined,進(jìn)而后面的條件進(jìn)行判斷;
    a.key === b.key && (
      (
        a.tag === b.tag &&
        a.isComment === b.isComment &&
        isDef(a.data) === isDef(b.data) &&
        sameInputType(a, b)
      ) || (
        isTrue(a.isAsyncPlaceholder) &&
        a.asyncFactory === b.asyncFactory &&
        isUndef(b.asyncFactory.error)
      )
    )
  )
}

使用key一定能提高diff效率么

答案是并不是,可以看下面的例子

<script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script>
<div id="app">
  <div class="ttt" v-for="(item) in list">{{item}}</div>
  <button @click="changeData">更新</button>
</div>
<script >
  new Vue({
    el: '#app',
    data() {
      return {
        list: [1, 2, 3]
      }
    },
    mounted(){
      Array.from(document.querySelectorAll('.ttt')).forEach(item=>{
        item.dataset.mm = item.textContent;
      })
    },
    methods:{
      changeData(){
        this.list = [4, 5, 6]
      }
    }
  })
</script>

初始dom結(jié)構(gòu)如下:

沒有key情況下更新數(shù)組,然后DOM結(jié)構(gòu)如下,可以看到dataset值沒有變化,可以初步判斷只是更新了div的內(nèi)容

使用數(shù)組元素作為key情況下更新數(shù)組,然后DOM結(jié)構(gòu)如下,可以看到dataset沒有了,可以初步判斷刪除和創(chuàng)建了新的dom,很明顯這樣處理效率更低。

vue源碼中的處理程序邏輯:
沒有key的情況: updateChildren -> 判定為同類型節(jié)點(diǎn)(div),執(zhí)行patchVnode方法 -> 再對div這個節(jié)點(diǎn)做updateChildren處理 -> 繼續(xù)patchVnode,最后的結(jié)果就是更新文本節(jié)點(diǎn)內(nèi)容;

if (oldVnode.text !== vnode.text) {
  nodeOps.setTextContent(elm, vnode.text)
}

有key并且key不相等: updateChildren -> key不同,判定不同類型節(jié)點(diǎn)(div),執(zhí)行createElm方法,進(jìn)而創(chuàng)建新的dom節(jié)點(diǎn);

為什么說使用index作為key容易出錯

  • 復(fù)現(xiàn)步驟:在第一行的Input里輸入1,在第二行Input里輸入2,然后點(diǎn)第一行的“ד刪除第一行
  • 期待結(jié)果:刪除第一行后,應(yīng)該變成“dog:2”
  • 實(shí)際結(jié)果:刪除第一行后,變成了“dog:1”
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<div id="app">
  <ul>
    <li v-for="(item, index) in list" :key="index">
      <test-row :name="item"></test-row>
      <span style="color: red;cursor: pointer" @click="handleRemove(index)">X</span>
    </li>
  </ul>
</div>
<script>
  Vue.component('test-row', {
    template: `<span>
      <span>{{ name }}:</span>
      <input v-model="nums"/>
      </span>`,
    props: {
      name: String
    },
    data() {
      return {
        nums: ''
      }
    }
  })
  new Vue({
    el: '#app',
    data() {
      return {
        list: ['cat', 'dog']
      }
    },
    methods: {
      handleRemove(i) {
        this.list.splice(i, 1);
      }
    }
  })
</script>

出現(xiàn)問題的原因:在patch階段會認(rèn)為這兩個input子節(jié)點(diǎn)是sameVnode,進(jìn)而復(fù)用原來的dom節(jié)點(diǎn),因?yàn)榻M件只觸發(fā)了更新,沒有重新創(chuàng)建實(shí)例, 所以組件實(shí)例data數(shù)據(jù)沒有變化,輸入框內(nèi)的內(nèi)容就不會變化。

如果使用dog、cat作為key就可以避免這個bug;

以上就是vue中key使用的問題示例解析的詳細(xì)內(nèi)容,更多關(guān)于vue key使用問題的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論