Why v-for doesn't react to change some element in array?
this.test[3] = 3
If later I will call push for array, only then Vue rerender content.
this.test[3] = 3;
this.push(4);
Example: https://codepen.io/anon/pen/debJqK
var vm = new Vue({ el: "#app", data: { test: [1, 2], }, methods: { changeVar1: function() { this.test[3] = 3; this.test.push(4); }, changeVar2: function() { this.test[3] = 3; } } })
html * { box-sizing: border-box; } body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; padding: 4em; }
<script src="https://cdn.jsdelivr.net/vue/1.0.26/vue.min.js"></script> <div id="app"> <button @click="changeVar1()">Work</button> <button @click="changeVar2()">Doesn't work</button> <p v-for="(index, digit) in test">{{digit}}</p> </div>
If you add elements by index, you have to call Vue.set()
:
Vue.set(this.test, 3, 3);
Or:
this.test.splice(3, 1, 3)
This enables Vue to adjust the reactivity to that element. Updated codePen .
Besides regular caveat problems, the docs have a specific guidance on arrays :
Caveats
Due to limitations in JavaScript, Vue cannot detect the following changes to an array:
- When you directly set an item with the index, eg
vm.items[indexOfItem] = newValue
- When you modify the length of the array, eg
vm.items.length = newLength
For example:
var vm = new Vue({ data: { items: ['a', 'b', 'c'] } }) vm.items[1] = 'x' // is NOT reactive vm.items.length = 2 // is NOT reactive
To overcome caveat 1, both of the following will accomplish the same as
vm.items[indexOfItem] = newValue
, but will also trigger state updates in the reactivity system:// Vue.set Vue.set(vm.items, indexOfItem, newValue) // Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)
You can also use the
vm.$set
instance method, which is an alias for the globalVue.set
:vm.$set(vm.items, indexOfItem, newValue)
To deal with caveat 2, you can use
splice
:vm.items.splice(newLength)
Updated stack snippet:
var vm = new Vue({ el: "#app", data: { test: [1, 2], }, methods: { changeVar1: function() { this.test[3] = 3; this.test.push(4); }, changeVar2: function() { Vue.set(this.test, 3, 3); // this.test.splice(3, 1, 3); // would work the same } } })
html * { box-sizing: border-box; } body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; padding: 4em; }
<script src="https://cdn.jsdelivr.net/vue/1.0.26/vue.min.js"></script> <div id="app"> <button @click="changeVar1()">Work</button> <button @click="changeVar2()">Didn't work, now fixed</button> <p v-for="(index, digit) in test">{{digit}}</p> </div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.