10

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?

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395

2 Answers2

7

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);
    }
},
bill.gates
  • 14,145
  • 3
  • 19
  • 47
0

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

data(){
 return {
  foo: 1
 }
}
Cristiano Soleti
  • 805
  • 7
  • 12
  • None of this is true. The example code is almost a direct copy from the Vue documentation, and as can be seen in the answer, apparently, works just fine. – Yuval Adam May 30 '20 at 18:30
  • What I said is all true. You literally changed the code :) – Cristiano Soleti May 30 '20 at 18:59
  • https://vuejs.org/v2/guide/components.html somewhere in the page it is explained why data should be a function, just to finalize my point :), sure it wasn't the reason why it wasn't working, but in all that spaghetti code, I couldn't really see the big picture – Cristiano Soleti May 30 '20 at 19:02