Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Referring to `this` vue component within an event handler

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?

like image 345
Yuval Adam Avatar asked May 30 '20 14:05

Yuval Adam


People also ask

How to define event handling methods in a Vue component?

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.

How to manually change the header of a Vue component?

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.

What is an event bus in Vue?

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.

How do I communicate between two components in a VUE project?

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.


1 Answers

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);
    }
},
like image 80
Ifaruki Avatar answered Oct 07 '22 02:10

Ifaruki