Reputation: 137
I'm trying to change the class of a single element within v-for loop on a mouseenter/mouseleave event but I'm confused on how to make it so that only the class on the element that is being hovered changes.
I've tried binding the class to a variable but that obviously causes all the elements in the list to change.
<template>
<ul>
<li class="item" v-for="item in items" @mouseenter="showInfoBar()" @mouseleave="hideInfoBar()">
<span class="infobar" :class="{ show : infoBar }"> </span>
</li>
</ul>
</template>
<script>
export default {
name: 'ItemsList',
props: ['items'],
data() {
return {
infoBar: false
}
},
methods: {
showInfoBar() {
this.infoBar = true
},
hideInfoBar() {
this.infoBar = false
}
}
}
</script>
Upvotes: 3
Views: 10020
Reputation: 112
You could use this instead
<template>
<ul>
<li class="item" v-for="(item, index) in items" :key="index" @mouseenter="infoBar = index" @mouseleave="infoBar = null">
<span class="infobar" :class="{ show : infoBar == index }"> </span>
</li>
</ul>
</template>
data() {
return {
infoBar: null
}
},
Upvotes: 2
Reputation: 627
I think instead of handling this as an array, the better approach should be handling it as separated components, I mean, is better practice to leave the state of each component to each component instead of handling the state of a collection of "components" in an array, I'm basing on React to this idea, you can declare ItemsList
and Item
as different components, and then for each Item, a separate state, please, tell me if you understand this approach, good luck.
I think also, once you refactor your code, instead of handling the state changing in two different methods, just declare a toggleMethod()
and make a logical denial to the current value of the state you are looking at the moment.
This is better:
function toggleState() {
this.someState = !this.someState;
}
Than this
function showState() {
this.someState = true;
}
function hideState() {
this.someState = false;
}
Good luck mate.
Upvotes: 0
Reputation: 6582
The problem is that you have infoBar
representing the state of all the info bars, when they should be controlled independently.
Turning infoBar
into an array, with each element representing the state of the info bar at that respective index should solve your problem.
<template>
<ul>
<li class="item" v-for="(item, index) in items" @mouseenter="showInfoBar(index)" @mouseleave="hideInfoBar(index)">
<span class="infobar" :class="{ show : infoBar[index] }"> </span>
</li>
</ul>
</template>
<script>
export default {
name: 'ItemsList',
props: ['items'],
data() {
return {
infoBar: []
}
},
mounted: function() {
for(var i = 0; i < this.items.length; i++) {
this.infoBar.push(false);
}
},
methods: {
showInfoBar(index) {
this.infoBar[index] = true;
},
hideInfoBar(index) {
this.infoBar[index] = false;
}
}
}
</script>
Upvotes: 0