Issue
I have a list like this:
var v = new Vue({
'el' : '#app',
'data' : {
'list' : [1,2,3,4,5,6,7,8,9,10]
},
methods: {
activateClass($event){
$event.target.classList.remove('animate');
void $event.target.offsetWidth;
$event.target.classList.add('animate');
},
changeRandomValue(){
var randomAmount = Math.round(Math.random() * 12);
var randomIndex = Math.floor(Math.random() * this.list.length);
Vue.set(this.list, randomIndex, randomAmount)
}
},
mounted(){
var vm = this;
setInterval(function(){
vm.changeRandomValue();
}, 500);
}
})
.animate{
animation: fade 0.5s;
}
@keyframes fade{
0% { background:blue; }
100% { background:white; }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.min.js"></script>
<div id="app">
<ul>
<li v-for="item in list" v-html="item" @click="activateClass($event)"></li>
</ul>
</div>
If you run the above snippet, you'll see that if you click an li it will use this code:
activateClass($event){
$event.target.classList.remove('animate');
void $event.target.offsetWidth;
$event.target.classList.add('animate');
}
To add a class to it once and play an animation (https://css-tricks.com/restart-css-animation/). Awesome!
Now, I also have a changeRandomValue()
function that selects one element from the list array and change its value.
How would I use the activateClass
method from inside of the changeRandomValue
method?
I've had a few thoughts about using events on the element, so it would be something like:
<li v-for="item in list" v-html="item"
@click="activateClass($event)"
@myValueChanged="activateClass($event)"
></li>
But I don't think anything like that exists. I have also been looking into watchers but I don't think this is really what they are for.
I have no problem taking the element that has been clicked and finding the data that it is referencing, but I can't work out how to take the data that has been changed and then find its dom reference.
The reason I'm not using class bindings is that I need to trigger a reflow. Maybe there is a really easy way to do that with vue, but I'm not aware of it.
Solution
One easy solution would be to use class bindings and the animationend
event.
You can also trigger the same solution programmatically, as shown in the mounted
event.
new Vue({
el: '#app',
data: {
items: [{
id: 1,
highlight: false
}, {
id: 2,
highlight: false
}]
},
mounted() {
// Demonstrate programmatic highlighting
setTimeout(() => {
this.items[1].highlight = true
setTimeout(() => {
this.items[1].highlight = true
}, 1000)
}, 1000)
},
methods: {
addClass(item) {
item.highlight = true
},
removeClass(item) {
item.highlight = false
}
}
})
p {
cursor: pointer;
}
.animate {
animation: fade 0.5s;
}
@keyframes fade {
0% {
background: blue;
}
100% {
background: white;
}
}
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p v-for="item in items" v-bind:class="{ animate: item.highlight }" v-on:click="addClass(item)" v-on:animationend="removeClass(item)">{{ item.id }}</p>
</div>
Answered By - Etheryte
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.