3

I have a vue single file component, which have a custom class instance as property: now i want to bind a event to a method of this class instance but i'm having issues, there is a simplified version of my code files

VueJS single file component

    <template>
        <div @click="class_prop.method"></div>
    </template>

    export default {
      data() {
        return {
            class_prop: new CustomClass(),
        };
      },
    }

CustomClass

    class CustomClass {
        constructor(){
            this.prop = 'default_value';
        }

        method(){
            this.prop = 'new_value';
            console.log(this.prop);
        }
    }

The error

When clicking on the page element i receive this error:

[Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'prop' of null"

But when i try to call the custom class method from the browser console (i'm using Chrome with Vue Devtools extension) i get NO error, it works correctly:

$vm0.class_prop.method()

Since i get two different behaviours of my code i cannot tell if it is my class wrong, the vue single file component, or something else.

2
  • 4
    Try: @click="() => class_prop.method()" Commented Dec 21, 2020 at 16:00
  • @WashingtonGuedes your solution work correctly, evenf if i can't figure out why and it means that vue js has 2 different behaviours for binding nested props and binding nested methods; if you write your comment as answer i'll mark it as accepted Commented Dec 21, 2020 at 16:18

2 Answers 2

1

Behind the scenes Vue somehow called or applied your method using null. Thus the error you've mentioned:

Error in v-on handler: "TypeError: Cannot read property 'prop' of null"


What can you do to workaround the problem?

You can use a lambda expression, so you can have full control of the object owner of the method, like this:

<div @click="() => class_prop.method()"></div>

You can also use the class instance in a method like this:

export default {
  data: () => ({
    foo: new CustomClass(),
  }),
  methods: {
    bar() {
      this.foo.method();
    },
  },
}

And then in your template:

<div @click="bar">{{ foo.prop }}</div>
Sign up to request clarification or add additional context in comments.

1 Comment

But not exactly correct - the linked code is used only if there are some event modifiers (see lines 109-120)
1

What you see is not Vue's fault, it's just plain JavaScript.

Here is a citation from great JS learning resource

The consequences of unbound this

If you come from another programming language, then you are probably used to the idea of a "bound this", where methods defined in an object always have this referencing that object. In JavaScript this is “free”, its value is evaluated at call-time and does not depend on where the method was declared, but rather on what object is “before the dot”.

Here is very simple example of consequences of above paragraphs (and why your code does not work):

class CustomClass {
  constructor() {
    this.prop = 'default_value';
  }

  method() {
    this.prop = 'new_value';
    console.log(this.prop);
  }
}

let instance = new CustomClass()

instance.method() // this works OK

let f = instance.method

f() // this does not! f is "unbound" ....have no "this"

2 Comments

I don't think so. In your example it throws error on undefined. In the OP code it throws error on null, which means somewhere vue called f.call(null, ...args) ... Maybe just data is not the place to have methods in vue :/
So ? Maybe Vue is doing something there but the point is without calling the method using the original instance, this is unbound. that's it...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.