2

I am learning Vue.js and at the moment i am learning to interact with the css, i really would love to know why my code doesn't work, basicly i have a button, when i click that button, every 1 second (i used setInterval for this, i tested the setInterval and it works) it should change between 2 classes that i have defined on my css, i have a higlight class, and a shrink class, and it should swap with each other in 1 second, when i enter the example, the second class is attached but passed 1 second no change happens, can you guys explain me why?

Html relevant part

<head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="styles.css"> </head> <body> <script src="https://unpkg.com/[email protected]"></script> <div id="exercise"> <!-- 1) Start the Effect with the Button. The Effect should alternate the "highlight" or "shrink" class on each new setInterval tick (attach respective class to the div with id "effect" below) --> <div> <button @click="startEffect">Start Effect</button> <div id="effect" :class="{highlight: effect,shrink: !effect}"></div> </div> 

Css

#effect { width: 100px; height: 100px; border: 1px solid black; } .highlight { background-color: red; width: 200px !important; } .shrink { background-color: gray; width: 50px !important; } 

Javascript

 new Vue({ el: '#exercise', data: { effect: true, }, methods: { startEffect: function() { setInterval(function(){ this.effect = !this.effect; console.log(this.effect); },1000); } } }); 

1 Answer 1

4

You lost context of your component inside the setInterval so your this is not the vue-component as you'd expect.

new Vue({ el: '#exercise', data: { effect: true, }, methods: { startEffect: function() { console.log(this) // add this line setInterval(function() { this.effect = !this.effect; console.log(this) // with this line, it will show you what went wrong console.log(this.effect); },1000); } } }) 

You can either do:

new Vue({ el: '#exercise', data: { effect: true, }, methods: { startEffect: function() { setInterval(() => { this.effect = !this.effect; console.log(this.effect); },1000); } } }) 

This works because with arrow functions this is bound to the enclosing scope.

or (ES5)

new Vue({ el: '#exercise', data: { effect: true, }, methods: { startEffect: function() { var vm = this setInterval(function() { vm.effect = !vm.effect; console.log(this.effect); },1000); } } }) 

This works as you are no longer using this inside the setInterval's callback but a variable vm that holds the context of your component.


See it working

new Vue({ el: '#exercise', data: { effect: true, }, methods: { startEffect: function() { setInterval(() => { this.effect = !this.effect; console.log(this.effect); },1000); } } })
#effect { width: 100px; height: 100px; border: 1px solid black; } .highlight { background-color: red; width: 200px !important; } .shrink { background-color: gray; width: 50px !important; }
<script src="https://vuejs.org/js/vue.min.js"></script> <div id="exercise"> <!-- 1) Start the Effect with the Button. The Effect should alternate the "highlight" or "shrink" class on each new setInterval tick (attach respective class to the div with id "effect" below) --> <div> <button @click="startEffect">Start Effect</button> <div id="effect" :class="{highlight: effect,shrink: !effect}"> </div> </div>

Sign up to request clarification or add additional context in comments.

7 Comments

it worked perfectly, i already saw something like that, and i know it has nothing to do with vue.js directly, but with javascript, can you just explain me why the 'this' is lost?
That would be a lot to explain and outside the scope of this question but I can link you to this stackoverflow.com/questions/591269/… and stackoverflow.com/questions/3127429/…. If you couldn't understand you can contact me :)
hmmm i didn't understand very well the example, do you know a simpler example to understand this?.. because i think this is really important since this is pure javascript :D
can't talk on chat don't have 20 reputation xD
|