Access Method from Vue Class Component Decorator inside a Watcher

5.1k views Asked by At

Essentially i have the same question as this and this issue on Github, which unfortunately were both closed before being answered :/

I am using Vue with Typscript and the Vue Class Components. What i need to do is to access a method of my (Vue-) Class from inside a watcher inside the @Component decorator. I know that it's possible to access the data of a component with this.$data, but what about methods.

My code works on runtime but produces compiletime-errors and errors in vscode ("Property 'clearInfo' does not exist on type 'Vue'.");

@Component({
  watch: {
    firstMesh(newMesh) {
      if (newMesh === undefined) this.clearInfo(1);   // this produces the errors
      else this.showMeshInfo(newMesh, 1);
    },
    secondMesh(newMesh) {
      if (newMesh === undefined) this.clearInfo(2);
      else this.showMeshInfo(newMesh, 2);
    },
  },
})


export default class Info extends Vue {
  clearInfo(whichMesh : number) {
...
  }

  showMeshInfo(mesh : any, index : number) {
    ....
  }


}
1

There are 1 answers

1
Bruno Francisco On BEST ANSWER

You have two options:

  1. Define the watch in the class itself
// first you need to install vue-property-decorators with npm i -S vue-property-decorator
// This library has a lot of useful decorators. You can read more about it here: https://github.com/kaorun343/vue-property-decorator

import { Vue, Component, Watch } from 'vue-property-decorator'


@Component
export default class Info extends Vue {
  @Watch('firstMesh')
  public watchFirstMesh(newValue) {
     // ... do whatever you need to do with the newValue here
  }

  @Watch('secondMesh')
  public watchSecondMesh(newValue) {
     // ... do whatever you need to do with the newValue here
  }
}
  1. define the watches and methods in the options part of @Component
@Component({
  watch: {
    firstMesh(newMesh) {
      if (newMesh === undefined) this.clearInfo(1);   // this produces the errors
      else this.showMeshInfo(newMesh, 1);
    },
    secondMesh(newMesh) {
      if (newMesh === undefined) this.clearInfo(2);
      else this.showMeshInfo(newMesh, 2);
    },
  },
  methods: {
   clearInfo(whichMesh : number) {
     ...
   },
   showMeshInfo(mesh : any, index : number) {
     ....
   }   
  }
})
export default class Info extends Vue {
  // Now you need to tell to typescript that there will be a method inside this class called clearInfo and showMeshInfo
  public clearInfo!: (wichMesh: number) => void;
  public showMeshInfo!: (mesh: any, index: number) => void;
}

Explanation

  1. The explanation can be read on the links I left

  2. Since you are defining the options in the decorator @Component({...}) this will be available in the context where the class will be instantiated. Typescript won't know what exactly is available (we wish it was that smart). You will have to tell it, that's why we have the public clearInfo!: (wichMesh: number) => void; part. If you don't know what this syntax means I will explain in short words and leave a link in the end:

public clearInfo!: (wichMesh: number) => void;

the ! part is called the non-null assertion operator. It is a way to tell the compiler "this expression cannot be null or undefined here, so don't complain about the possibility of it being null or undefined."

The (wichMesh: number) => void; is the function signature. Basically it says: this will be a function that receives as the first argument a number (whichMesh) and returns void (=> void)

Non null assertion typescript Function signature typescript