
Security News
Deno 2.6 + Socket: Supply Chain Defense In Your CLI
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.
vue-property-decorator
Advanced tools
This library fully depends on vue-class-component, so please read its README before using this library.
MIT License
npm i -S vue-property-decorator
There are several decorators and 1 function (Mixin):
@Prop@PropSync@Model@ModelSync@Watch@Provide@Inject@ProvideReactive@InjectReactive@Emit@Ref@VModel@Component (provided by vue-class-component)Mixins (the helper function named mixins provided by vue-class-component)@Prop(options: (PropOptions | Constructor[] | Constructor) = {}) decoratorimport { Vue, Component, Prop } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@Prop(Number) readonly propA: number | undefined
@Prop({ default: 'default value' }) readonly propB!: string
@Prop([String, Boolean]) readonly propC: string | boolean | undefined
}
is equivalent to
export default {
props: {
propA: {
type: Number,
},
propB: {
default: 'default value',
},
propC: {
type: [String, Boolean],
},
},
}
Note that:
type property of each prop value from its type definition, you can use reflect-metadata.emitDecoratorMetadata to true.reflect-metadata before importing vue-property-decorator (importing reflect-metadata is needed just once.)import 'reflect-metadata'
import { Vue, Component, Prop } from 'vue-property-decorator'
@Component
export default class MyComponent extends Vue {
@Prop() age!: number
}
It's not supported to define each default property like @Prop() prop = 'default value' .
@PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {}) decoratorimport { Vue, Component, PropSync } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@PropSync('name', { type: String }) syncedName!: string
}
is equivalent to
export default {
props: {
name: {
type: String,
},
},
computed: {
syncedName: {
get() {
return this.name
},
set(value) {
this.$emit('update:name', value)
},
},
},
}
@PropSync works like @Prop besides the fact that it takes the propName as an argument of the decorator, and also creates a computed getter and setter behind the scenes. This way you can interface with the property as if it was a regular data property whilst making it as easy as appending the .sync modifier in the parent component.
@Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) decoratorimport { Vue, Component, Model } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@Model('change', { type: Boolean }) readonly checked!: boolean
}
is equivalent to
export default {
model: {
prop: 'checked',
event: 'change',
},
props: {
checked: {
type: Boolean,
},
},
}
@Model property can also set type property from its type definition via reflect-metadata .
@ModelSync(propName: string, event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) decoratorimport { Vue, Component, ModelSync } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@ModelSync('checked', 'change', { type: Boolean })
readonly checkedValue!: boolean
}
is equivalent to
export default {
model: {
prop: 'checked',
event: 'change',
},
props: {
checked: {
type: Boolean,
},
},
computed: {
checkedValue: {
get() {
return this.checked
},
set(value) {
this.$emit('change', value)
},
},
},
}
@ModelSync property can also set type property from its type definition via reflect-metadata .
@Watch(path: string, options: WatchOptions = {}) decoratorimport { Vue, Component, Watch } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@Watch('child')
onChildChanged(val: string, oldVal: string) {}
@Watch('person', { immediate: true, deep: true })
onPersonChanged1(val: Person, oldVal: Person) {}
@Watch('person')
onPersonChanged2(val: Person, oldVal: Person) {}
}
is equivalent to
export default {
watch: {
child: [
{
handler: 'onChildChanged',
immediate: false,
deep: false,
},
],
person: [
{
handler: 'onPersonChanged1',
immediate: true,
deep: true,
},
{
handler: 'onPersonChanged2',
immediate: false,
deep: false,
},
],
},
methods: {
onChildChanged(val, oldVal) {},
onPersonChanged1(val, oldVal) {},
onPersonChanged2(val, oldVal) {},
},
}
@Provide(key?: string | symbol) / @Inject(options?: { from?: InjectKey, default?: any } | InjectKey) decoratorimport { Component, Inject, Provide, Vue } from 'vue-property-decorator'
const symbol = Symbol('baz')
@Component
export class MyComponent extends Vue {
@Inject() readonly foo!: string
@Inject('bar') readonly bar!: string
@Inject({ from: 'optional', default: 'default' }) readonly optional!: string
@Inject(symbol) readonly baz!: string
@Provide() foo = 'foo'
@Provide('bar') baz = 'bar'
}
is equivalent to
const symbol = Symbol('baz')
export const MyComponent = Vue.extend({
inject: {
foo: 'foo',
bar: 'bar',
optional: { from: 'optional', default: 'default' },
baz: symbol,
},
data() {
return {
foo: 'foo',
baz: 'bar',
}
},
provide() {
return {
foo: this.foo,
bar: this.baz,
}
},
})
@ProvideReactive(key?: string | symbol) / @InjectReactive(options?: { from?: InjectKey, default?: any } | InjectKey) decoratorThese decorators are reactive version of @Provide and @Inject. If a provided value is modified by parent component, then the child component can catch this modification.
const key = Symbol()
@Component
class ParentComponent extends Vue {
@ProvideReactive() one = 'value'
@ProvideReactive(key) two = 'value'
}
@Component
class ChildComponent extends Vue {
@InjectReactive() one!: string
@InjectReactive(key) two!: string
}
@Emit(event?: string) decoratorThe functions decorated by @Emit $emit their return value followed by their original arguments. If the return value is a promise, it is resolved before being emitted.
If the name of the event is not supplied via the event argument, the function name is used instead. In that case, the camelCase name will be converted to kebab-case.
import { Vue, Component, Emit } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
count = 0
@Emit()
addToCount(n: number) {
this.count += n
}
@Emit('reset')
resetCount() {
this.count = 0
}
@Emit()
returnValue() {
return 10
}
@Emit()
onInputChange(e) {
return e.target.value
}
@Emit()
promise() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(20)
}, 0)
})
}
}
is equivalent to
export default {
data() {
return {
count: 0,
}
},
methods: {
addToCount(n) {
this.count += n
this.$emit('add-to-count', n)
},
resetCount() {
this.count = 0
this.$emit('reset')
},
returnValue() {
this.$emit('return-value', 10)
},
onInputChange(e) {
this.$emit('on-input-change', e.target.value, e)
},
promise() {
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve(20)
}, 0)
})
promise.then((value) => {
this.$emit('promise', value)
})
},
},
}
@Ref(refKey?: string) decoratorimport { Vue, Component, Ref } from 'vue-property-decorator'
import AnotherComponent from '@/path/to/another-component.vue'
@Component
export default class YourComponent extends Vue {
@Ref() readonly anotherComponent!: AnotherComponent
@Ref('aButton') readonly button!: HTMLButtonElement
}
is equivalent to
export default {
computed() {
anotherComponent: {
cache: false,
get() {
return this.$refs.anotherComponent as AnotherComponent
}
},
button: {
cache: false,
get() {
return this.$refs.aButton as HTMLButtonElement
}
}
}
}
@VModel(propsArgs?: PropOptions) decoratorimport { Vue, Component, VModel } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@VModel({ type: String }) name!: string
}
is equivalent to
export default {
props: {
value: {
type: String,
},
},
computed: {
name: {
get() {
return this.value
},
set(value) {
this.$emit('input', value)
},
},
},
}
The vue-class-component package allows you to define Vue components using class-style syntax in TypeScript. It provides a base class for Vue components and supports decorators for properties and methods. Compared to vue-property-decorator, it is more lightweight but requires additional packages for full decorator support.
The vuex-class package provides TypeScript decorators and helpers for Vuex. It allows you to use class-style syntax to define Vuex modules, actions, getters, and mutations. While it focuses on Vuex integration, it complements vue-property-decorator by providing similar decorator-based syntax for Vuex.
FAQs
property decorators for Vue Component
The npm package vue-property-decorator receives a total of 208,755 weekly downloads. As such, vue-property-decorator popularity was classified as popular.
We found that vue-property-decorator demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Deno 2.6 introduces deno audit with a new --socket flag that plugs directly into Socket to bring supply chain security checks into the Deno CLI.

Security News
New DoS and source code exposure bugs in React Server Components and Next.js: what’s affected and how to update safely.

Security News
Socket CEO Feross Aboukhadijeh joins Software Engineering Daily to discuss modern software supply chain attacks and rising AI-driven security risks.