Je voulais créer un composant qui obtient une zone de texte lorsque la souris survole l'image.
Ci-dessous, le modèle HTML.
<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>
Et ci-dessous se trouve 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
}
}
});
Lorsque j'exécute les codes ci-dessus, je peux constater que la propriété show a changé. Cependant, v-if n'est pas mis à jour. Ne pouvons-nous pas utiliser array [index] pour v-if ou y a-t-il une autre raison?
Le problème ne concerne pas v-if
, C'est parce que Vue ne peut pas détecter directement les changements d'un élément de tableau, c'est l'une des limitations de JavaScript.
Ainsi, Vue fournit quelques fonctions d'assistance pour cela, comme Vue.set
Modifiez ce this.show[index] = !this.show[index]
à Vue.set(this.show, index, !this.show[index])
alors ça devrait marcher.
Vue.set
N'est pas la seule solution, il existe plusieurs façons d'y parvenir, au cas où vous voudriez le savoir.
Vous pouvez utiliser des méthodes natives de tableau JavaScript, Vue accrochera ces méthodes afin qu'il puisse détecter les changements.
Voici l'exemple d'utilisation de .splice
this.show.splice(index, 1, !this.show[index])
Une autre façon consiste à remplacer entièrement le tableau. Si vous utilisez ES6, vous pouvez utiliser l'opérateur d'étalement pour cloner le tableau facilement:
this.show[index] = !this.show[index]
this.show = [...this.show]
.map
Fonctionnera également car il renvoie un nouveau tableau
this.show = this.show.map((el, i) =>
i === index ? !el : el
)
Vous pouvez utiliser un JS objet au lieu d'un tablea et obtenir le même effet. En d'autres termes, remplacez show: [false, false, false],
avec show: {0:false, 1:false, 2:false},
.
Dans le composant dans les méthodes, vous pouvez utiliser:
this.$set(this.show, index, !this.show[index])