Given this Vue component that attaches a global event listener:
var app = new Vue({
data: {
foo: 0;
},
methods: {
handle: function(e) {
this.foo = 1; // this refers to handler, not app
}
},
mounted: function() {
window.addEventListener("keypress", this.handle);
}
});
What is the correct way to refer to this
from within the event handler in order to update the component state? Alternatively, is there a better way to set event handlers on the entire window
?
Luckily, Vue allows us to define event handling methods on the component. All we need to do is pass the name of the component’s method to the v-on directive: Sometimes we want to be able to pass information to our method calls or even consume the DOM event itself.
The manual change of the Test.vue component occurs inside the method section and emits an event through the event bus. The statement tells Vue to emit an event called changeIt and pass the string changed header as argument. After setting up the event, we need to make the second component listen and react to the event.
Essentially, an event bus is a Vue.js instance that can emit events in one component, and then listen and react to the emitted event in another component directly — without the help of a parent component. By definition, using an event bus is more efficient than using event emitters because it requires less code to run.
Vue has a way of communicating between two child components through a parent component using event emitters. When you set up an event in a child component and a listener in the parent component, the reaction is passed down through the parent to the nested components. While this is a valuable solution, it can become clumsy as your project grows.
Actually this
is binded to the vue instance and your code works fine.
var app = new Vue({
el: "#app",
data: {
foo: 0
},
methods: {
handle: function(e) {
this.foo++;
console.log(this.foo);
}
},
mounted: function() {
window.addEventListener("keypress", this.handle);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
{{ foo }}
</div>
The common mistake is if you have for example an function with an callback and you try to use this
inside the callback, it will be undefined
handle: function(e) {
this.foo++;
setTimeout(function(){
console.log(this.foo); //undefined
})
console.log(this.foo);
}
You could either use arrow functions
handle: function(e) {
this.foo++;
setTimeout(() =>{
console.log(this.foo);
})
console.log(this.foo);
}
},
Or if its need to be backwards compatible you could use .bind()
handle: function(e) {
this.foo++;
setTimeout(function(){
console.log(this.foo);
}.bind(this))
console.log(this.foo);
}
},
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