Make your VueJS code look more fabulous with class decorator (part 1)
Look at VueJS community and decorator apply
The debate between the options API and the compositions API in VueJS has been a hot topic among the developer community since the release of the compositions API in Vue 3.0. Both approaches have their own unique benefits and drawbacks, and choosing the right one will have a big impact on the contribution of your team.
Today, I will intro with you to another way to build Vue project look cooler with class setup and decorator as functionality support. Moreover, we can taste the mixing of traditional javascript class style and compositions API in your Vue 3.0 projects.
Create VueJS project
npm init vue@latest
✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add an End-to-End Testing Solution? … No / Cypress / Playwright
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
Scaffolding project in ./<your-project-name>...
Done.
> cd <your-project-name>
> npm install
> npm run dev
In official documents of Vue community provide us with some recommendations for using a more modern Vue style in compositions API:
You should now have your first Vue project running! Note that the example components in the generated project are written using the Composition API and <script setup>, rather than the Options API.
Using decorator by vue-facing-decorator
The library is designed for Vue 3 to write Vue components in classes. Works on TypeScript and decorator.
- The community desired Vue class component with typescript decorators.
- Safety. Transform es class to Vue options API according to specifications.
- Performance. Once transform on project loading, ready for everywhere.
- Support ES class inherit, Vue
extends
, and Vuemixins
.
Add to a project right now by using the command to download the package from NPM:
npm i vue-facing-decorator
Enable experimentalDecorators
in tsconfig.json
in the project root
directory:
{
"compilerOptions": {
"experimentalDecorators": true
}
}
How to use it?
Define a class component
The simplest class component must extend Vue base class and be decorated by
Component
from this workspace.
import { Component, Vue } from 'vue-facing-decorator'
@Component
class MyComponent extends Vue {}
In Vue single-file components
<template>
<div></div>
</template>
<script lang="ts">
// DO NOT USE <script setup>
// Vue options API
/*
import { defineComponent } from "vue";
export default defineComponent({});
*/
// Class component
import { Component, Vue } from "vue-facing-decorator";
@Component
export default class MyComponent extends Vue {}
</script>
In separated files with TSX
If you don't want to use single-file components, this is another choice. It use
.ts
file to define component and import template from .tsx
file.
import type Comp from './Comp'
import Style from './style.css'
export default function render(this: Comp) {
return (
<div class={Style.root} onClick={this.onClick}>
{this.counter}
</div>
)
}
import { Component, Base } from 'vue-facing-decorator'
import render from './Comp.render'
@Component({ render })
export default class Component extends Base {
counter = 1
onClick() {
this.counter++
}
}
.root {
background-color: red;
}
The features and performances
@Component decorator
Use the decorator Component
to decorate a class that extends from Vue base
class.
import { Component, Vue } from 'vue-facing-decorator'
@Component({
...options, // option here
})
export default class MyComponentWithOptions extends Vue {}
You can find out further detail about options API via official documents:
@Property decorator
In a class component, we could define data of Vue options API as class
properties directly. This repo will analyze properties and transform them as the
return value of data
function.
import { Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
property = 'property value'
}
@Method decorator
In a class component, we could define methods of vue options API as class
methods directly. This repo will analyze methods and transform them into
methods
options.
import { Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
method() {
console.log('This is method! ')
}
}
@Hook decorator
Class component supports almost all lifecycle hooks in vanilla Vue. Write them as class methods directly. Hooks won't be transformed into methods.
import { Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
mounted() {}
}
Vue has many built-in hooks for life-cycle as the internal hook. It can not be replaced by override. Your custom hook name must have a different name from that one.
;[
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeUpdate',
'updated',
'activated',
'deactivated',
'beforeDestroy',
'beforeUnmount',
'destroyed',
'unmounted',
'renderTracked',
'renderTriggered',
'errorCaptured',
'serverPrefetch',
'render',
]
Component props decorator
Use Prop
decorator to define a property in Vue's props.
import { Prop, Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
@Prop
isOpen?: boolean
}
This decorator can expand to more functionality as validation and type support. You can find out further detail about options API via official documents:
Accessor decorator
Property getters will be transformed into { computed: { get: Foo } }
import { Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
name = 'Michael Jackson'
get getter() {
return this.name
}
set setter(name: string) {
this.name = name
}
}
Event decorator
We could define a method that triggers a Vue event by Emit
decorator. The
decorator received an optional event name parameter. Event
will be triggered
with this name and the method returned value. If the event name parameter is
omitted, use the method's name by default.
import { Emit, Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
@Emit
triggerMethodNameEvent() {
return 'triggerMethodNameEvent value'
}
@Emit('SpecifiedName')
triggerSpecifiedNameEvent() {
return 'triggerSpecifiedNameEvent value'
}
}
If one event method returns a promise, Event
will be triggered after the
promise is resolved with the promise value.
import { Emit, Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
@Emit
triggerAsyncEvent() {
return new Promise((resolver) => {
setTimeout(() => {
resolver('value')
}, 1000)
})
}
}
Reference decorator
Use Ref
decorator to define a property getter this.$refs[name] on Vue
component instance. The reference name is the name of the property.
import { Ref, Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
@Ref
readonly refEl!: HTMLDivElement
}
@Watch decorator
Use Watch
decorator to define a watcher in Vue's watch.
The first parameter is the name watched. Same as Vue watch
, the watcher
receives two parameters: new value and old value.
import { Watch, Component, Vue } from 'vue-facing-decorator'
@Component
export default class MyComponent extends Vue {
property = 'value'
@Watch('property')
propertyWatcher(newValue: string, oldValue: string) {}
}
You can find out further detail about options API via official documents:
Conclusion
I introduced you to how to make your Vue code by other styles based on using
vue-facing-decorator
support. I will have completed decorator styling for
store management by Vuex module decorator in the next article. See you soon!
Reference resources
Vue-facing-decorator documentation
© Bùi Quốc Khải.