之前做過這樣的一個需求,就是輸入框可動態增加或者減少的場景。通過v-for來遍歷所有輸入框,那麼分析下面key幾種情況:
爲了演示,這裏假設輸入框的校驗規則是允許字符數爲1-5。
1.沒有綁定key 或者 key綁定index的情況
如圖所示,第二個輸入框輸入了6個字符,校驗不通過,但是第三個輸入框校驗是通過的,但是當我們刪除第二個輸入框的時候,第三個輸入框變爲第二個輸入框,本來校驗通過的,現在反而不通過了。
分析:當dom發生變化的時候,vue進行dom進行的增刪,藉助vnode的key比較,第二個輸入框綁定的key爲2,第三個輸入綁定的輸入框爲3,那麼將第二個輸入框刪除後,第三個輸入框變爲第二個輸入框,這時候vue刪除key爲3的節點,key爲2的節點依舊存在,替換的僅僅是輸入框的值,那麼就會出現上面這種情況。
2.key綁定唯一值的情況
通過下面這個函數生成唯一值:
uuid (index) {
return `uuid-${index}-${Date.now()}-${Math.random().toFixed(2)}`;
}
爲了解決第一種情況出現,我們嘗試將key綁定唯一值,但是出現另外一個bug。
如圖所示,第一種情況的問題在這裏確實能得到解決,但是每當我在輸入框輸入的時候,一輸入一個字符就會出現失去焦點。
分析:每當值發生變化,vue就會重新渲染。因爲我的key值是通過時間戳和隨機數來生成,所以重新渲染的時候,節點的key肯定和上一次不一樣,那麼vue會將所有節點全部替換,所以出現失焦的情況。
3.key仍舊綁定唯一值的情況
將綁定的唯一key存起來,當輸入後,重新渲染的時候,用上次的key,而不是重新新的key,這樣就能解決第2種情況出現的問題
分析:如下面代碼展示,將唯一key存進keyList裏面,然後下次渲染仍舊用上次的key
<el-form :model="form">
<el-form-item class="main-container" v-for="(item, index) in form.list" :key="keyList[index]"
:prop="'list.' + index + '.value'"
:rules="{
validator: validateName, trigger: 'blur'
}">
<el-input class="main-input" v-model="item.value"></el-input>
<el-button v-if="index === form.list.length -1" @click="add(index)">+</el-button>
<el-button v-if="form.list.length > 1" @click="sub(index)">-</el-button>
</el-form-item>
</el-form>
add和sub函數在增刪輸入框的同時,也對keyList進行增刪
data () {
var validateName = (rule, value, callback) => {
if (value === '') {
callback(new Error('輸入不能爲空'));
} else {
if (value.length > 5) {
callback(new Error('輸入項不能超過5個字符'));
}
}
};
return {
form: {
list: [
{
value: ''
}
]
},
keyList: [this.uuid(0)],
validateName
}
},
methods: {
add (index) {
this.keyList.push(this.uuid(index));
this.form.list.push({value: ''})
},
sub (index) {
this.keyList.splice(index, 1);
this.form.list.splice(index, 1);
},
uuid (index) {
return `uuid-${index}-${Date.now()}-${Math.random().toFixed(2)}`;
}
}
完整代碼地址:https://github.com/suhuashan/vue-blog
如果對您有幫助,請star下~