Reputation: 121
I have already created this effect in an old vanilla js app. I have a series of blocks that have a hover animation, and when there is no hover, the animation cycles block by block in succession.
I have rebuilt the whole app in Vue js, and everything else has been much easier. This is the only part of the app that I am struggling to do the "Vue" way with no dom manipulation. Basically I have a 3 second timeout where the component gets the "active" class, and then the class switches to the next component in the v-for.
Any suggestions?
Upvotes: 0
Views: 353
Reputation: 29102
You should just need to represent the relevant state using properties in data
. Whenever you feel tempted to manipulate the DOM directly just update some state instead and wire that up to the template accordingly.
Hopefully this demo does what you want:
new Vue({
el: '#app',
data () {
return {
active: 0,
items: [
'Red',
'Green',
'Blue',
'Yellow'
]
}
},
mounted () {
this.startTimer()
},
destroyed () {
this.stopTimer()
},
methods: {
onMouseEnter (index) {
this.stopTimer()
this.active = index
},
onMouseLeave () {
this.startTimer()
},
startTimer () {
if (this.timerId) {
return
}
this.timerId = setInterval(() => {
this.active = (this.active + 1) % 4
}, 500)
},
stopTimer () {
clearInterval(this.timerId)
this.timerId = null
}
}
})
ul {
border: 1px solid #777;
margin: 0;
padding: 0;
}
li {
list-style: none;
padding: 5px;
}
.active {
background: #ccf;
}
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
<ul>
<li
v-for="(item, index) in items"
:key="item"
:class="{ active: active === index }"
@mouseenter="onMouseEnter(index)"
@mouseleave="onMouseLeave"
>
{{ item }}
</li>
</ul>
</div>
Upvotes: 1