skip to Main Content

In this example I have an object that got a name as a string parameter and a function that just logs this

const me = reactive({
  name: "foo",
  sayHi: function () {
    console.log("Hi I am : ", this);
  },
});

In the template I instentiate another component that after 3000ms of it creation emits an event sayHi. This component is created twice :

  1. <Comp :name="me.name" @sayHi="me.sayHi"/>
  2. <Comp :name="me.name" @sayHi="me.sayHi()"/>

I kind of understand the diffrence between an event handler with and without parentheses explained here but I can’t understand why the this in the first one is undefined but in the second one its the object itself as I expect.

2

Answers


  1. When v-on directive is provided with @sayHi="me.sayHi()" inline expression, it’s wrapped with a function and compiled to something like:

    el.addEventListener('sayHi', $event => { vm.me.sayHi() })
    

    When a value is a function value like @sayHi="me.sayHi", event handler is a function itself:

    el.addEventListener('sayHi', vm.me.sayHi)
    

    As explained in this question, this context is not parent object when its method is used as a callback, and this happens when it’s passed as event handler. A function should be explicitly bound to the desired context to receive it as this.

    The difference with this question is that sayHi is not component method. Component methods in Vue options API are internally bound to component instance, this doesn’t apply to composition API.

    sayHi should refer reactive value explicitly instead of using this:

    const me = reactive({
      name: "foo",
      sayHi: () => {
        console.log("Hi I am : ", me.name);
      },
    });
    

    There’s no benefit from using sayHi function as a method of reactive object, it’s ignored by Vue reactivity API. Unless there are reasons for me to be an object, e.g. it’s passed to other components, a state and function could be separated:

    const me = ref("foo")
    const sayHi = () => {
        console.log("Hi I am : ", me.value);
    };
    
    Login or Signup to reply.
  2. Event call compiles differently

    // <Comp :name="me.name" @sayHi="me.sayHi"/>
    let fn = me.sayHi
    fn($event) // `this` is undefined us you just calling a function
    

    and

    // <Comp :name="me.name" @sayHi="me.sayHi()"/>
    // or
    // <Comp :name="me.name" @sayHi="() => me.sayHi()"/>
    let fn = () => me.sayHi()
    fn($event) // `this` is `me` as you are calling an object method
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search