VueJS v-if = array [index] not working

I wanted to create a component that receives a text box when the mouse is over the image.

Below is the HTML template.

<section class="item-container" v-for="(item, index) in items"> <div class="image-box" @mouseenter="changeStatus(index)"> <img class="image" src="item.link" alt> </div> <div class="text-box" @mouseleave="changeStatus(index)" v-if="show[index]"> <h4>{{ item.name }}</h4> <p>{{ item.content }}</p> </div> </section> 

And below is app.js

 new Vue({ el: '#app', data: { show: [false, false, false], items: [ { name: 'Author 1', content: 'Content 1' }, { name: 'Author 2', content: 'Content 2' }, { name: 'Author 3', content: 'Content 3' } ] }, methods: { changeStatus: function(index) { this.show[index] = !this.show[index]; console.log(this.show); console.log(this.show[index]); // console gets it as expected } } }); 

When I execute the above codes, I can detect that the show property has changed. However, v-if is not updated. Can't we use the [index] array for v-if, or are there any other reasons for this?

+6
source share
2 answers

The problem is not v-if , because Vue cannot directly detect changes to an array element, this is one of the limitations of JavaScript.

Thus, Vue provides some helper functions for this, for example Vue.set

Change this this.show[index] = !this.show[index]

to Vue.set(this.show, index, !this.show[index])

then it should work.

Vue.set is not the only solution, there are several ways to do this if you want to find out.

You can use your own methods for the JavaScript array, Vue will use these methods so that it can detect changes.

Here is an example using .splice

this.show.splice(index, 1, !this.show[index])

Another way is to completely replace the array. If you are using ES6, you can use the spread operator to easily clone the array:

 this.show[index] = !this.show[index] this.show = [...this.show] 

.map will also work because it returns a new array

 this.show = this.show.map((el, i) => i === index ? !el : el ) 
+12
source

You can use a JS object instead of an array and get the same effect. In other words, replace show: [false, false, false], with show: {0:false, 1:false, 2:false},

0
source

Source: https://habr.com/ru/post/1013960/


All Articles