0

I am using a lambda expression within the methods section of a Vuejs component.

The example is below I trigger alertyou() and get the alert, click okay. Then in the vue developer tools I see this.activated becomes true.

export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App',
      activated: false
    }
  },
  methods: {
      alertme: () => { alert('Clicked'); this.activated = false; },
      alertyou() {
        alert('Alert You');
        this.activated = true
      }
  }
}

However, when I click the button that triggers the alertme lambda. I get the alert message, click okay. But then this.activated stays true!

What is going on here is this a limitation with lambdas? Can you only trigger one statement per lambda? Or does this have to deal with scope once an alert is fired?

christopher clark
  • 2,026
  • 5
  • 28
  • 47
  • No, arrow functions are not limited to have only one statement within. Change alert for console.log and test it again - do not use alert, as it is blocking statement. –  Nov 12 '17 at 19:22
  • @WaldemarIce `alert` will not block anything from being executed. The issue is that using an arrow function binds `this` to the parent scope, which is not the Vue instance. He should define `alertme` as a regular function (or use the shorthand like he has with `alertyou`). He doesn't need to explicitly bind to `this`. – thanksd Nov 12 '17 at 19:30
  • @thanksd Read above comments. I know where he have problem - with scope. And you are wrong, alert is code blocking statement. If you call it, code execution is literally paused. –  Nov 12 '17 at 19:33
  • Ups, I was wrong :) But alert is blocking :) One of two blocking nonsenses in JS :) Everything else is non-blocking :) –  Nov 12 '17 at 19:38
  • @WaldemarIce I see what you mean. Yes, `alert` will pause the script execution. But, after the alert is dismissed the rest of the `alertme` function will get called. I thought you were saying it wouldn't. – thanksd Nov 12 '17 at 19:58

2 Answers2

2

What is going on here is this a limitation with lambdas? Can you only trigger one statement per lambda? Or does this have to deal with scope once an alert is fired?

It’s neither.

An arrow function keeps this bound to the context it was when the arrow function was created. In this case, this is not the vue instance. It’s probably window

A function declared on an object using the function keyword (or the ES6 object shorthand style) will normally have this bound to the object on which the function is declared.

That’s why you can access this.activated on alertyou but not alertme

You’ll want to use the same syntax as alertyouto declare the alertme method.

akatakritos
  • 9,836
  • 1
  • 23
  • 29
  • I get it now, how could I continue to use the arrow function syntax though? – christopher clark Nov 12 '17 at 19:49
  • Why do you want to? – akatakritos Nov 12 '17 at 20:00
  • 1
    @christopherclark The bad news is that you simply cannot use arrow functions to define methods on the Vue instance like that. There are a lot of questions on the vue-related SO tags about issues caused by this misunderstanding. Vue, from the get-go does some behind the scenes magic to bind `this` to the Vue instance and it simply does not support arrow functions. Using an arrow function will always bind `this` to the context of the parent scope. In your case, since this appears to be a single file component in node, you are binding `this` to `undefined`. – thanksd Nov 12 '17 at 20:05
1

Change alertme: () => { alert('Clicked'); this.activated = false; } to alertme() { alert('Clicked'); this.activated = false; }. You can see a working example here

Eyk Rehbein
  • 3,683
  • 3
  • 18
  • 39
  • A little explanation along with the code would surely help. – yuriy636 Nov 12 '17 at 19:39
  • Of course: As @thanksd mentioned above in the comments of the main post, the arrow functions binds `this` to the parent scope which isn't the Vue instance in this case. And because of this you need to use a normal Javascript function which you initialize with `function alertme() { }` or as you can see above with `alertme() { }` which is a ES6 shortcut. – Eyk Rehbein Nov 12 '17 at 19:44