Vue 專案開發之疑難雜症
1、使用v-model 繫結物件的動態屬性,導致v-model失效或者資料異常
場景:使用iview的CheckboxGroup 做checkbox多選時,發現勾選的選項和v-model繫結物件對應的屬性值不匹配。
template程式碼如下:
<CheckboxGroup v-else-if="item.formType === 'checkbox'" v-model="metaTemplate[item.name]"> <Checkbox v-for="(check, index) in JSON.parse(item.formValue)" :key="index" :label="check"></Checkbox> </CheckboxGroup>
這裡面checkbox的值和個數都是通過介面返回動態引數決定的,v-model繫結到一個叫meteTemplate物件的屬性上,而這個屬性也是動態新增上去的。怪異的問題是:假設現在checkbox有三個,當全部選中三個時,這時候預期的結果是繫結的物件屬性是一個含有三個值的陣列,但實際是含有一個值的陣列,看起來感覺v-model出現問題了,即UI變化沒有反應到資料上。
template物件定義如下:
data () {
return {
metaTemplate: {
}
},
它是一個簡單的空物件,物件屬性是動態加上去的,錯誤截圖如下:
這裡看到UI的狀態和資料並不保持一致,感覺很怪異。
嘗試辦法:
(1) 重新定義一個屬性使用v-model和checkbox繫結,發現正常工作。
(2)在metaTemplate中預選定義一個屬性,例如metaTemplate{checkArr:[]}, 發現頁正常工作。
思考:
從上面的嘗試辦法看出不是元件本身的問題,不是物件屬性巢狀的問題,這次最大的不同就是繫結的屬性是後來加到物件上去的,即v-model是物件的一個動態屬性,於是就思考動態屬性是不是需要特殊處理後才能適用於v-model?
解決辦法:
原因:
見Vue.js中文官網->進階->深入響應式原理->變化檢測問題
受現代 JavaScript 的限制(以及廢棄 Object.observe),Vue 不能檢測到物件屬性的新增或刪除。由於 Vue 會在初始化例項時對屬性執行 getter/setter 轉化過程,所以屬性必須在 data 物件上存在才能讓 Vue 轉換它,這樣才能讓它是響應的。例如:
方案:
1、使用 Vue.set(object, key, value) 方法將響應屬性新增到巢狀的物件上:
Vue.set(vm.someObject, 'b', 2) 2、您還可以使用 vm.$set 例項方法,這也是全域性 Vue.set 方法的別名:
this.$set(this.someObject,'b',2) 3、使用 Object.assign() 或 _.extend() 方法來新增屬性
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
例項解決辦法:
this.$set(this.metaTemplate, item.name, [])
2、iview表單驗證規則遇到非string型別時,如果不明確指明型別,則可能驗證失敗
場景:很多表單項都需要驗證是否為空,現有一項表單為多選的checkbox繫結的值,最終資料應該是一個數組,驗證規則如下:
{ required: true, message: '請輸入該欄位', trigger: 'blur' }
但勾選了選項後,點選確認提交表單,發現表單驗證不通過,在checkbox下面提示:‘請輸入該欄位’。
思考:明顯是驗證規則有問題,發現沒有明確指定驗證的type型別。
解決辦法:
{ required: true, type: 'array', message: '請輸入該欄位', trigger: 'blur' }