Vue Class Component
Vue Class Component provides ES201X/TypeScript class decorators that allow developers to write Vue components using a class-based syntax, leveraging features like decorators, inheritance, and strong typing. The current stable version, 7.2.6, is designed for Vue 2.x projects. While Vue 3 primarily uses the Composition API, this library offered a structured approach for large Vue 2 applications, particularly for those coming from object-oriented backgrounds or using TypeScript extensively. The project has moved towards a 'maintenance' state for the Vue 2 compatible version, with active development on a beta version (v8) targeting Vue 3. Release cadence for v7.x has been irregular, with bug fixes and minor improvements. Its key differentiator is simplifying component definition and lifecycle management with TypeScript classes, providing a more organized code structure compared to the Options API for complex components.
Common errors
-
Cannot read property '$route' of undefined
cause Attempting to access Vue Router properties (e.g., this.$route, this.$router) in class property initializers before the component instance is fully set up.fixMove the initialization logic for properties dependent on Vue Router to the `created()` or `mounted()` lifecycle hooks. Example: `data() { return { id: this.$route.params.id } }` or `created() { this.id = this.$route.params.id }`. -
Argument of type 'typeof Component' is not assignable to parameter of type 'VueConstructor<Vue>'
cause Incorrectly trying to instantiate a class-based component directly with `new Vue(MyComponent)` or expecting it to behave exactly like an Options API object where a `Vue.extend` might be missing.fixClass components are typically used directly in Vue templates or within `render` functions, for example: `h(MyComponent)` or `components: { MyComponent }`. If manually creating an instance, it's usually `new MyComponent()`, but often it's handled by Vue's reactivity system. -
Property 'myMethod' does not exist on type 'CombinedVueInstance<Vue, ...>'. Did you mean 'myMethod'?
cause TypeScript IntelliSense for class component methods or properties is not working correctly, often due to missing type definitions or an issue with the project's TypeScript configuration.fixEnsure `vue-class-component` is correctly installed, TypeScript is configured, and if you're expecting enhanced lifecycle hook IntelliSense, verify `import 'vue-class-component/hooks'` is included as per v7.2.1 changes.
Warnings
- breaking The `mixins` helper type compatibility was temporarily broken, requiring specific type parameters which is not recommended. v7.2.5 and v7.2.6 fixed this to retain backward compatibility. Manually specifying mixin types like `mixins<Foo & Bar>(Foo, Bar)` is discouraged.
- gotcha TypeScript IntelliSense support for lifecycle methods was disabled by default in v7.2.1 to prevent potential breakage of existing components. If you rely on this, you must explicitly import a side-effect module.
- gotcha When using `vue-class-component` with Vue Router properties (like `$route`, `$router`) in property initializers (e.g., `data = this.$route.params.id`), it might lead to `undefined` errors because the router is not yet initialized. v7.2.4 addressed some cases.
- gotcha Vue Class Component v7.x is designed for Vue 2.x. While a v8 beta exists for Vue 3, attempting to use v7.x with Vue 3 will lead to incompatibility issues.
Install
-
npm install vue-class-component -
yarn add vue-class-component -
pnpm add vue-class-component
Imports
- Component
import { Component } from 'vue-class-component'import Component from 'vue-class-component'
- mixins
import { mixins } from 'vue-class-component'import Component, { mixins } from 'vue-class-component' - hooks (for IntelliSense)
import { hooks } from 'vue-class-component'import 'vue-class-component/hooks'
Quickstart
import Vue from 'vue'
import Component from 'vue-class-component'
interface MyData {
message: string
count: number
}
@Component({
props: {
propMessage: String
}
})
export default class MyComponent extends Vue {
// Initial data
message: string = 'Hello from Vue Class Component!'
count: number = 0
// Declared props
readonly propMessage!: string
// Computed property
get reversedMessage(): string {
return this.message.split('').reverse().join('')
}
// Method
increment(): void {
this.count++
}
// Lifecycle hook
mounted(): void {
console.log('Component mounted with prop:', this.propMessage)
console.log('Initial message:', this.message)
}
// Template rendered implicitly or via a render function
render(h: Function) {
return h('div', [
h('h2', this.message),
h('p', `Prop message: ${this.propMessage}`),
h('p', `Count: ${this.count}`),
h('p', `Reversed: ${this.reversedMessage}`),
h('button', { on: { click: this.increment } }, 'Increment')
])
}
}
// To use this component
// new Vue({
// el: '#app',
// render: h => h(MyComponent, { props: { propMessage: 'A prop value!' } })
// })