Yuval Adam
Yuval Adam

Reputation: 165182

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?

Upvotes: 10

Views: 3466

Answers (2)

Cristiano Soleti
Cristiano Soleti

Reputation: 858

Your data property should be a function, not an object.

data(){
 return {
  foo: 1
 }
}

Upvotes: 0

Ilijanovic
Ilijanovic

Reputation: 14904

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);
    }
},

Upvotes: 7

Related Questions