Vue項(xiàng)目中v-for數(shù)組刪除第n項(xiàng)元素產(chǎn)生渲染錯(cuò)誤問題及解決方法

項(xiàng)目背景

最近使用Vue(版本2.9)開發(fā)一個(gè)項(xiàng)目時(shí)卖毁,要生成表單列表池颈,所以使用了v-for來做循環(huán)怀薛,循環(huán)里的元素(item)是一個(gè)子組件刺彩。同時(shí)每個(gè)元素都有刪除按鈕,點(diǎn)擊后刪除當(dāng)前元素枝恋。
初始代碼如下:
父組件:

<template>
    <div class="content-body">
        <div>任務(wù)</div>
          <div>
            <ul>
              <li v-for="(item,index) in selectionConditionList" :key="index" style="margin:10px 0">
                <v-selection-condition-list></v-selection-condition-list> <button @click="deleteSelectionCondition(index)">刪除</button>
              </li>
            </ul>
          </div>
          <div>
             <button @click="addNewSelectionTask">新建任務(wù)</button>
          </div>
    </div>
</template>

<script>
/* eslint-disable */
import vSelectionConditionList from './SelectionConditionList'
  export default
  {
    data()
    {
      return {
        selectionConditionList:[],
      }
    },
    methods: {
      // 添加新的用戶篩選條件
      addNewSelectionTask(){
        this.selectionConditionList.push({});
      },
      // 刪除用戶篩選條件
      deleteSelectionCondition(index){
        console.log("delete.."+index);
        this.selectionConditionList.splice(index,1);
      }
    },
    components:{
      vSelectionConditionList
    }
  }
</script>
<style>
  .div_center {
    text-align: center;;
    width:100%;
    margin:0 auto;
  }
</style>

子組件:

<template>
  <input type="text" :value="inputName">
</template>

<script>
/* eslint-disable */
  export default
  {
    data()
    {
      return {
        inputName: Math.random()
      }
    },
    methods: {
    }
  }
</script>

出現(xiàn)的問題

運(yùn)行代碼后创倔,點(diǎn)擊新建任務(wù),出現(xiàn)的結(jié)果如下圖:


859708731-5aab87f763329_articlex.png

點(diǎn)擊第一行的刪除按鈕焚碌,預(yù)期當(dāng)然是刪掉第一行三幻。然而出現(xiàn)的結(jié)果卻是最后一行被刪掉了,而其他元素未變呐能。刪除中間某元素也是最后一行被刪掉念搬。這時(shí)通過console控制臺(tái)的打印輸出可以看到,刪除的index索引是正確的摆出。本人是vue新手朗徊,遇到此問題有些懵,查詢官方文檔及百度相關(guān)問題無果后偎漫,在segmentfault問答區(qū)提問爷恳,當(dāng)時(shí)問題鏈接。然鵝提問一天以后象踊,收到的回答還是沒有完全解決問題温亲,于是繼續(xù)尋求解決方案棚壁。
解決方法


經(jīng)過再次苦苦查詢相關(guān)問題的問答帖及文章,終于發(fā)現(xiàn)問題是出在v-for的:key上栈虚。關(guān)于v-for中的:key介紹參見此頁面:Vue2.0 v-for 中 :key 到底有什么用袖外?,內(nèi)容一大堆balabala魂务,總之是由于虛擬DOM的原因引起的曼验,我的理解就是:表單列表的生成是通過綁定的selectionConditionList數(shù)組來生成的,當(dāng)selectionConditionList刪除掉一項(xiàng)時(shí)粘姜,表單列表的dom對(duì)象自然也會(huì)減少一項(xiàng)鬓照。但是由于v-for循環(huán)的是子組件,子組件內(nèi)部顯示數(shù)據(jù)并未綁定selectionConditionList數(shù)組里的屬性孤紧,因此子組件的顯示數(shù)據(jù)并未按新數(shù)組重新渲染豺裆,體現(xiàn)出來的結(jié)果就是最后一個(gè)元素被刪掉了。
解決方法就是給:key賦予一個(gè)獨(dú)一無二的值号显,這樣綁定的數(shù)組就可以和dom對(duì)象一一對(duì)應(yīng)起來臭猜,刪除的時(shí)候也能正確刪除掉響應(yīng)dom對(duì)象了。綁定這個(gè)“獨(dú)一無二”的值咙轩,其中一個(gè)方法就是使用guid,也就是Global Unique Identifier阴颖,于是把生成guid的方法寫到了一個(gè)公共的js文件里活喊,:key綁定guid值,測試ok量愧,大功告成钾菊!
代碼如下:
父組件:

<template>
    <div class="content-body">
        <div>任務(wù)</div>
          <div>
            <ul>
              <li v-for="(item,index) in selectionConditionList" :key="item.guid" style="margin:10px 0">
                <v-selection-condition-list></v-selection-condition-list> <button @click="deleteSelectionCondition(index)">刪除</button>
              </li>
            </ul>
          </div>
          <div>
             <button @click="addNewSelectionTask">新建任務(wù)</button>
          </div>
    </div>
</template>

<script>
/* eslint-disable */
import Utils from '../utils/utils.js'
import vSelectionConditionList from './SelectionConditionList'
  export default
  {
    data()
    {
      return {
        selectionConditionList:[],
      }
    },
    methods: {
      // 添加新的用戶篩選條件
      addNewSelectionTask(){
        this.selectionConditionList.push({guid:Utils.guid()});
      },
      // 刪除用戶篩選條件
      deleteSelectionCondition(index){
        console.log("delete.."+index);
        this.selectionConditionList.splice(index,1);
      }
    },
    components:{
      vSelectionConditionList
    }
  }
</script>
<style>
  .div_center {
    text-align: center;;
    width:100%;
    margin:0 auto;
  }
</style>

子組件:

<template>
  <input type="text" :value="inputName">
</template>

<script>
/* eslint-disable */
  export default
  {
    data()
    {
      return {
        inputName: Math.random()
      }
    },
    methods: {
    }
  }
</script>

guid方法:

/* eslint-disable */
var utils = {
  guid: function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random() * 16 | 0,
        v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  }
}
export default utils

后話

此問題只出現(xiàn)在v-for嵌套子組件的情況下。如果是v-for循環(huán)一個(gè)div或表單對(duì)象偎肃,而對(duì)象中的數(shù)據(jù)都是通過數(shù)組中的對(duì)象屬性綁定的煞烫,那么數(shù)組刪除其中一項(xiàng)后,dom對(duì)象列表也可以相應(yīng)正確渲染累颂。有興趣的話可以把子組件換成input對(duì)象滞详,然后在selectionConditionList中添加類似{val:Math.random()}這樣的數(shù)據(jù),實(shí)測刪除后是沒有問題的紊馏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末料饥,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子朱监,更是在濱河造成了極大的恐慌岸啡,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赫编,死亡現(xiàn)場離奇詭異巡蘸,居然都是意外死亡奋隶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門悦荒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唯欣,“玉大人,你說我怎么就攤上這事逾冬∈蚰簦” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵身腻,是天一觀的道長产还。 經(jīng)常有香客問我,道長嘀趟,這世上最難降的妖魔是什么脐区? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮她按,結(jié)果婚禮上牛隅,老公的妹妹穿的比我還像新娘。我一直安慰自己酌泰,他們只是感情好媒佣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著陵刹,像睡著了一般默伍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衰琐,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天也糊,我揣著相機(jī)與錄音,去河邊找鬼羡宙。 笑死狸剃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的狗热。 我是一名探鬼主播钞馁,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼匿刮!你這毒婦竟也來了指攒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤僻焚,失蹤者是張志新(化名)和其女友劉穎允悦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡隙弛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年架馋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片全闷。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叉寂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出总珠,到底是詐尸還是另有隱情屏鳍,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布局服,位于F島的核電站钓瞭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淫奔。R本人自食惡果不足惜山涡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唆迁。 院中可真熱鬧鸭丛,春花似錦、人聲如沸唐责。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鼠哥。三九已至熟菲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肴盏,已是汗流浹背科盛。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工帽衙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留菜皂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓厉萝,卻偏偏與公主長得像恍飘,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谴垫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容