That's a word of caution when it comes to reactivity. One workaround is to utilize the Vue.set()
method:
<script type="text/javascript" src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2254574762100c170c1314">[email protected]</a>/dist/vue.js"></script>
<!-- Letter 'a', 'b', 'c' shows only when its corresponding shows[] is true-->
<div id="app">
<p v-show="shows[0]">a</p>
<p v-show="shows[1]">b</p>
<p v-show="shows[2]">c</p>
<button @click="currentShow=(currentShow+1)%3">next</button>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
currentShow: 0,
shows:[true, false, false],
},
watch:{
currentShow: function (val, old) {
Vue.set(this.shows, old, false);
Vue.set(this.shows, val, true);
}
}
});
</script>
Read more in the Docs:
If you are making modifications or additions based on an index, remember to use Vue.set()
:
Vue.set(this.shows, old, false);
Vue.set(this.shows, val, true);
Alternatively:
this.shows.splice(old, 1, false);
this.shows.splice(val, 1, true);
This approach helps Vue maintain reactivity for that specific element.
The Reasoning Behind It
Alongside the typical caveat issues, the documentation provides specific advice regarding arrays:
Caveats
Due to JavaScript limitations, Vue cannot detect these types of
changes within an array:
- Directly setting an item using the index, e.g.,
vm.items[indexOfItem] = newValue
- Adjusting the length of the array, e.g.,
vm.items.length = newLength
For example:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // does NOT trigger reactivity
vm.items.length = 2 // does NOT trigger reactivity
To address issue 1, both methods below achieve the same outcome as
vm.items[indexOfItem] = newValue
, and also prompt state changes
within the reactivity system:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
You can also utilize the vm.$set
instance method, which serves as a shorthand for the global Vue.set
:
vm.$set(vm.items, indexOfItem, newValue)
To tackle issue 2, utilize the splice
method:
vm.items.splice(newLength)