下面我就為大家分享一篇解決Vue無法偵測陣列或物件變動的問題,具有很好的參考價值,希望對大家有幫助。
來看一個實例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"></script> <style> li:hover { cursor: pointer; } </style> </head> <body> <p class="wrap"> <ul> <li v-for="item,index in items" v-on:click="handle(index)"> <span>{{item.name}}</span> <span>{{numbers[index]}}</span> </li> </ul> </p> <script> var vm = new Vue({ el: ".wrap", data: { numbers: [], items: [ {name: 'jjj'}, {name: 'kkk'}, {name: 'lll'}, ] }, methods: { handle: function (index) { // WHY: 更新数据,view层未渲染,但通过console这个数组可以发现数据确实更新了 if (typeof(this.numbers[index]) === "undefined" ) { // 注:下面这么设置是可以的。例如 // var arr = []; // arr[3]=3; // console.log(arr) //[empty × 3, 3] this.numbers[index] = 1; // this.numbers.splice(index,0,1) //用splice方法能同步显示,但得不到想要的效果 } else { this.numbers[index]++; // this.numbers.splice(index,1,this.numbers[index]++) } // console.log(this.numbers) } } }); </script> </body> </html>
想實現的效果是點擊li 看vm.nymbers[index] 是否存在,不存在設置為1,存在的話加1。
點擊之後數字並沒有在view層更新,而透過console列印發現資料更新了,只是view層沒有及時的偵測到。
再看一個改動之後的:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"></script> <style> li:hover { cursor: pointer; } </style> </head> <body> <p class="wrap"> <ul> <li v-for="item,index in items" v-on:click="handle(index)"> <span>{{item.name}}</span> <!--<span>{{numbers[index]}}</span>--> </li> </ul> </p> <script> var vm = new Vue({ el: ".wrap", data: { // numbers: [], items: [ {name: 'jjj'}, {name: 'kkk'}, {name: 'lll'}, ] }, methods: { handle: function (index) { // 不是数组,这里更新数据就可以直接在view层渲染 this.items[index].name += " success"; // console.log(this.numbers) } } }); </script> </body> </html>
可以看到這裡的view層能及時得到更新,但是到了數組哪裡為什麼就不可以了呢?
來看Vue2.0官方的文件說明:
#由於JavaScript 的限制,Vue 無法偵測以下變動的陣列:
當你利用索引直接設定一個項目時,例如:vm.items[indexOfItem] = newValue
當你修改陣列的長度時,例如:vm.items.length = newLength
為了解決第一類問題,以下兩種方式都可以實現和vm.items[indexOfItem] = newValue 相同的效果,同時也會觸發狀態更新:
// Vue.set Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice example1.items.splice(indexOfItem, 1, newValue)
你也可以使用vm.$ set 實例方法,它只是全域Vue.set 的別名。
還是由於 JavaScript 的限制,Vue 無法偵測物件屬性的新增或刪除:
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 现在是响应式的 vm.b = 2 // `vm.b` 不是响应式的
對於已經建立的實例,Vue 無法動態新增根層級的回應式屬性。但是,可以使用 Vue.set(object, key, value) 方法為嵌套物件新增響應式屬性。例如,對於:
var vm = new Vue({ data: { userProfile: { name: 'Anika' } } })
有時你可能需要為已有物件賦予多個新屬性,例如使用 Object.assign() 或 _.extend()。在這種情況下,你應該用兩個物件的屬性來建立一個新的物件。所以,如果你想加入新的回應式屬性,不要像這樣:
Object.assign(this.userProfile, { age: 27, favoriteColor: 'Vue Green' })
應該要這樣做:
this.userProfile = Object.assign({}, this.userProfile, { age: 27, favoriteColor: 'Vue Green' })
因此,上面範例應該改為:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue</title> <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"></script> <style> li:hover { cursor: pointer; } </style> </head> <body> <p class="wrap"> <ul> <li v-for="item,index in items" v-on:click="handle(index)"> <span>{{item.name}}</span> <span>{{numbers[index]}}</span> </li> </ul> </p> <script> var vm = new Vue({ el: ".wrap", data: { numbers: [], items: [ {name: 'jjj'}, {name: 'kkk'}, {name: 'lll'}, ] }, methods: { handle: function (index) { if (typeof(this.numbers[index]) === "undefined" ) { this.$set(this.numbers, index, 1); //(arr,index,newvalue) } else { this.$set(this.numbers, index, ++this.numbers[index]); } } } }); </script> </body> </html>
搞定!
1.17補充-------------------------------
如何理解「對於已經建立的實例,Vue 不能動態新增根層級的回應式屬性」?
例如:
var vm=new Vue({ el:'#test', data:{ //data中已经存在info根属性 info:{ name:'小明' } } }); //给info添加一个性别属性 Vue.set(vm.info,'sex','男');
上面是正確做法,下面的做法的話就會報錯了:
Vue.set(vm.data,'sex','男')
實際上,不能直接在data上增加屬性,但可以在data裡的物件上增加屬性。
實際上vm.data是undefined。
上面是我整理給大家的,希望今後對大家有幫助。
相關文章:
vue中手機號碼,郵件信箱正規驗證以及60s發送驗證碼的實例
以上是如何解決Vue不能檢測數組或物件變動方面問題?的詳細內容。更多資訊請關注PHP中文網其他相關文章!