I am learning Vue and facing a problem while using arrow function in computed property.
My original code works fine (See snippet below).
new Vue({
el: '#app',
data: {
turnRed: false,
turnGreen: false,
turnBlue: false
},
computed:{
switchRed: function () {
return {red: this.turnRed}
},
switchGreen: function () {
return {green: this.turnGreen}
},
switchBlue: function () {
return {blue: this.turnBlue}
}
}
});
.demo{
width: 100px;
height: 100px;
background-color: gray;
display: inline-block;
margin: 10px;
}
.red{
background-color: red;
}
.green{
background-color: green;
}
.blue{
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.js"></script>
<div id="app">
<div class="demo" @click="turnRed = !turnRed" :class="switchRed"></div>
<div class="demo" @click="turnGreen = !turnGreen" :class="switchGreen"></div>
<div class="demo" @click="turnBlue = !turnBlue" :class="switchBlue"></div>
</div>
However, after I change methods in computed property, the color will not change (though the turnRed value still switch between true and false successfully).
This is my code:
computed:{
switchRed: () => {
return {red: this.turnRed}
},
switchGreen: () => {
return {green: this.turnGreen}
},
switchBlue: () => {
return {blue: this.turnBlue}
}
}
Do I use the wrong syntax ?
While you should not use arrow functions to define methods, it's fine to use them inside your methods as the this keyword will bind to the correct parent reference. const app = Vue.
You can call a method from computed properties or watchers.
Arrow functions cannot be used to write object methods because, as you have found, since arrow functions close over the this of the lexically enclosing context, the this within the arrow is the one that was current where you defined the object.
The Basics of Vue Reactivity Simply put, a computed property's dependencies are the reactive values that help the property that determine the value that is returned. If none of these change, then, again, the cached value will be returned. If no reactive dependency is changed, a computed property is not recalculated.
You are facing this error because an arrow function wouldn't bind this
to the vue instance for which you are defining the computed property. The same would happen if you were to define methods
using an arrow function.
Don’t use arrow functions on an instance property or callback (e.g.
vm.$watch('a', newVal => this.myMethod()))
. As arrow functions are bound to the parent context, this will not be the Vue instance as you’d expect andthis.myMethod
will be undefined.
You can read about it here.
The arrow function lost the Vue component context. For your functions in methods
, computed
, watch
, etc., use the Object functions:
computed:{
switchRed() {
return {red: this.turnRed}
},
switchGreen() {
return {green: this.turnGreen}
},
switchBlue() {
return {blue: this.turnBlue}
}
}
You can achive this by deconstructing what you want from this:
computed:{
switchRed: ({ turnRed }) => {red: turnRed},
switchGreen: ({ turnGreen }) => {green: turnGreen},
switchBlue: ({ turnBlue }) => {blue: turnBlue}
}
And why not something simpler like this?
new Vue({
el: '#app',
data: {
turnRed: false,
turnGreen: false,
turnBlue: false
},
methods:{
toggle (color) {
this[`turn${color}`] = !this[`turn${color}`];
}
}
});
.demo{
width: 100px;
height: 100px;
background-color: gray;
display: inline-block;
margin: 10px;
}
.red{
background-color: red;
}
.green{
background-color: green;
}
.blue{
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.js"></script>
<div id="app">
<div class="demo" @click="toggle('Red')" :class="{red:turnRed}"></div>
<div class="demo" @click="toggle('Green')" :class="{green: turnGreen}"></div>
<div class="demo" @click="toggle('Blue')" :class="{blue: turnBlue}"></div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With