Skip to content
This repository has been archived by the owner on Feb 7, 2024. It is now read-only.

@Emit, @Ref and @Watch decorators are not working for the class that inherits the generic class (v10.0.0-rc.3) #394

Closed
maxdzin opened this issue Jul 25, 2021 · 2 comments

Comments

@maxdzin
Copy link

maxdzin commented Jul 25, 2021

Hi everyone!
First of all, thanks for such a great library.
I'm trying to use it with vite + vue 3 and I've faced a few issues.

Describe the bug
The @emit, @ref and @watch decorators are not working for the class that inherits the generic class.

  • The @watch decorator works only for the successor class properties or computed properties, the ancestor generic class properties or computed properties changes are not triggered.
  • The @emit works only for for the ancestor generic class, in the successor class the emit methods are not called.
  • The @ref decorator is not working in successor class, only works if declare in ancestor generic class.

To Reproduce
Steps to reproduce the behavior:

interface IRecord {
  [field: string]: unknown
}
type TSuccessor = IRecord & { id: string }

class EntityBase<T extends IRecord> extends Vue {
  recordList: T[] = []
}

class EntitySuccessor extends EntityBase<TSuccessor> {
  @Ref() readonly someFileInput!: HTMLInputElement // this ref is undefined.

  @Emit('select')
  emitSelect(record: IRecord): IRecord {
    return record // this emit method is not called.
  }

  @Watch('recordList', { deep: true })
  recordListChange(): void {
    console.log('Record list change') // this watcher is not triggered as expected when recordList changes.
  }
}

Expected behavior
The @emit, @ref and @watch decorators should work well in the successor class that inherits generic class.

Desktop (please complete the following information):

  • OS: Windows 10 Pro (20H2 (OS Build 19042.1110))
  • Browser: Chrome, Firefox, Edge
  • Version: 10.0.0-rc.3

Additional context
package.json versions:

  • "vue": "^3.1.5"
  • "vue-class-component": "^8.0.0-rc.1"
  • "vue-property-decorator": "^10.0.0-rc.3"
  • "vite": "^2.4.3"
@maxdzin maxdzin changed the title @Emit, @Ref and @Watch decorators are not working for the class that inherits the generic class @Emit, @Ref and @Watch decorators are not working for the class that inherits the generic class (v10.0.0-rc.3) Jul 26, 2021
@nros
Copy link

nros commented Jan 28, 2022

This is not the fault of vue-property-decorator, this is not a bug, its a technical limitation of VueJS!!

see #396

@maxdzin VueJS does not support inheritance at all. AFAIK you can not use a custom base class with your component. This is a limitation based on the technical implementation of Vue 2 and can not be changed. I guess, it is the same with Vue 3.

To overcome this limitiation and provide some simulation of inheritance, Vue uses mix-ins. see: https://vuejs.org/v2/guide/mixins.html

import { Mixins } from "vue-property-decorator";

export default class EntitySuccessor extends Mixins(EntityBase<TSuccessor>) {

technical explanation

(see: https://github.com/vuejs/vue/blob/v2.6.14/src/core/global-api/extend.js)
Under the hood the @Component decorator calls Vue's API function extend to create the component. This function does not expect to receive a class. It just regards the passed-on class as an object with properties. So, a new default prototype for the component is created and the original base class prototype is just disposed. Therefore, the only base class you can use is Vue. This is the reason, why all component examples extend Vue only and why the SFC TypeScript definition does the same. You can not extend any other base class. You have to use mixins instead. Mixins will copy over all properties and methods of the base class to your component.

(see Line 33)

const Sub = function VueComponent (options) {
    this._init(options)
}
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub

@maxdzin
Copy link
Author

maxdzin commented Jan 28, 2022

Thank you, @nros for a quite clear explanation.
And you're right, I've learned a lot regarding it since I've posted this issue here, so, yes, that is not an issue with vue-property-decorator.

@maxdzin maxdzin closed this as completed Jan 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants