SoFunction
Updated on 2025-04-04

Detailed explanation of the use of vue-property-decorator and vux-class in Vue decorator

Currently, in projects developed with vue, TypeScript will be used to perform some constraints. In order to improve development efficiency, it is often usedDecoratorsTo simplify our code.

This article mainly introduces decoratorsvue-property-decoratorand vux-classUse of

1. Installation

npm i -S vue-property-decorator
npm i -S vuex-class

2. vue-property-decorator

  • @Component
  • @Prop
  • @PropSync
  • @Model
  • @ModelSync
  • @Watch
  • @Provide
  • @Inject
  • @ProvideReactive
  • @InjectReactive
  • @Emit
  • @Ref
  • @VModel

@Component

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

@Component({
 components:{
      componentA,
      componentB,
  }
})
export default class MyComponent extends Vue{
   
}

Equivalent to:

export default{
  name: 'MyComponent',
  components:{
    componentA,
    componentB,
  }
}

@Prop

@Prop(options: (PropOptions | Constructor[] | Constructor) = {}) decorator

express:@PropThe decorator receives a parameter, which can be written in three ways:

  • PropOptions: The following options can be used: type, required, default, validator
  • Constructor: For example, String, Number, Boolean, etc., specify the type of prop
  • Constructor[]: Specify the optional type of prop

For example:

import { Vue, Component, Prop } from 'vue-property-decorator'
 
@Component
export default class MyComponent extends Vue {
  @Prop(Number) readonly propA: number | undefined
  @Prop({ default: 'default value' }) readonly propB!: string
  @Prop([String, Boolean]) readonly propC: string | boolean | undefined
}

Equivalent to:

export default {
  name: 'MyComponent',
  props: {
    propA: {
      type: Number,
    },
    propB: {
      default: 'default value',
    },
    propC: {
      type: [String, Boolean],
    },
  },

@PropSync

@PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {}) decorator
  • propName represents the attribute name passed by the parent component
  • Parent components need to be combined.syncCome to use

For example:

// 
import { Vue, Component, PropSync } from 'vue-property-decorator'
 
@Component
export default class MyComponent extends Vue {
  @PropSync('name', { type: String }) syncedName!: string
<!--  -->
<template>
  <div>
    <MyComponent  :="name" />
  </div>
</template>

Equivalent to:

export default {
  name: 'MyComponent',
  props: {
    name: {
      type: String,
    },
  },
  computed: {
    syncedName: {
      get() {
        return 
      },
      set(value) {
        this.$emit('update:name', value)
      },
    },
  },
}

@PropSyncWorking principle and@PropSimilarly, in addition to accepting propName as the decorator parameter, it also creates a computed getter and setter behind the scenes. This way you can use the property as you would with a regular data property, while adding it in the parent component.syncModifiers are as simple as that.

@Model

@ModelThe decorator allows us to customize the v-model on a component.

@Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) decorator

For example:

import { Vue, Component, Model } from 'vue-property-decorator'
 
@Component
export default class MyComponent extends Vue {
  @Model('change', { type: Boolean }) readonly checked!: boolean
}

Equivalent to:

export default {
  model: {
    prop: 'checked',
    event: 'change',
  },
  props: {
    checked: {
      type: Boolean,
    },
  },
}

@ModelSync

@ModelSync(propName: string, event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) decorator

For example:

import { Vue, Component, ModelSync } from 'vue-property-decorator'
 
@Component
export default class MyComponent extends Vue {
  @ModelSync('checked', 'change', { type: Boolean }) readonly checkedValue!: boolean
}

Equivalent to:

export default {
  model: {
    prop: 'checked',
    event: 'change',
  },
  props: {
    checked: {
      type: Boolean,
    },
  },
  computed: {
    checkedValue: {
      get() {
        return 
      },
      set(value) {
        this.$emit('change', value)
      },
    },
  },
}

@Watch

@Watch(path: string, options: WatchOptions = {}) decorator

For example:

import { Vue, Component, Watch } from 'vue-property-decorator'
 
@Component
export default class MyComponent 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) {}
}

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 | @Inject

@Provide(key?: string | symbol) decorator
@Inject(options?: { from?: InjectKey, default?: any } | InjectKey) decorator

For example:

import { 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'
}

Equivalent to:

const symbol = Symbol('baz')
 
export const MyComponent = ({
  inject: {
    foo: 'foo',
    bar: 'bar',
    optional: { from: 'optional', default: 'default' },
    baz: symbol,
  },
  data() {
    return {
      foo: 'foo',
      baz: 'bar',
    }
  },
  provide() {
    return {
      foo: ,
      bar: ,
    }
  },
})

@ProvideReactive | @InjectReactive

They are@providerand@Injectresponsive version of . If the parent component modifies the provided value, the child component can capture this modification.

@ProvideReactive(key?: string | symbol)  decorato
@InjectReactive(options?: { from?: InjectKey, default?: any } | InjectKey) decorator

For example:

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

@Emit(event?: string) decorator

For example:

import { Vue, Component, Emit } from 'vue-property-decorator'
 
@Component
export default class MyComponent extends Vue {
  count = 0
 
  @Emit()
  addToCount(n: number) {
     += n
  }
 
  @Emit('reset')
  resetCount() {
     = 0
  }
 
  @Emit()
  returnValue() {
    return 10
  }
 
  @Emit()
  onInputChange(e) {
    return 
  }
 
  @Emit()
  promise() {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(20)
      }, 0)
    })
  }
}

Equivalent to:

export default {
  data() {
    return {
      count: 0,
    }
  },
  methods: {
    addToCount(n) {
       += n
      this.$emit('add-to-count', n)
    },
    resetCount() {
       = 0
      this.$emit('reset')
    },
    returnValue() {
      this.$emit('return-value', 10)
    },
    onInputChange(e) {
      this.$emit('on-input-change', , e)
    },
    promise() {
      const promise = new Promise((resolve) => {
        setTimeout(() => {
          resolve(20)
        }, 0)
      })
 
      ((value) => {
        this.$emit('promise', value)
      })
    },
  },
}

@Ref

Ref(refKey?: string) decorator

For example:

import { Vue, Component, Ref } from 'vue-property-decorator'
 
import AnotherComponent from '@/path/to/'
 
@Component
export default class MyComponent extends Vue {
  @Ref() readonly anotherComponent!: AnotherComponent
  @Ref('aButton') readonly button!: HTMLButtonElement
}

Equivalent to:

export default {
  computed() {
    anotherComponent: {
      cache: false,
      get() {
        return this.$ as AnotherComponent
      }
    },
    button: {
      cache: false,
      get() {
        return this.$ as HTMLButtonElement
      }
    }
  }
}

@VModel

@VModel(propsArgs?: PropOptions) decorator

For example:

import { Vue, Component, VModel } from 'vue-property-decorator'
 
@Component
export default class MyComponent extends Vue {
  @VModel({ type: String }) name!: string
}

Equivalent to:

export default {
  props: {
    value: {
      type: String,
    },
  },
  computed: {
    name: {
      get() {
        return 
      },
      set(value) {
        this.$emit('input', value)
      },
    },
  },
}

3. vuex-class

@State@Getter@Action@Mutationnamespace

import Vue from 'vue'
import Component from 'vue-class-component'
import {
  State,
  Getter,
  Action,
  Mutation,
  namespace
} from 'vuex-class'

const someModule = namespace('path/to/module')

@Component
export class MyComponent extends Vue {
  @State('foo') stateFoo
  @State(state =&gt; ) stateBar
  @Getter('foo') getterFoo
  @Action('foo') actionFoo
  @Mutation('foo') mutationFoo
  @('foo') moduleGetterFoo

  // If the parameters are omitted, use the attribute name of each state/getter/action/mutation type directly  @State foo
  @Getter bar
  @Action baz
  @Mutation qux

  created () {
     // -&gt; 
     // -&gt; 
     // -&gt; 
    ({ value: true }) // -&gt; ('foo', { value: true })
    ({ value: true }) // -&gt; ('foo', { value: true })
     // -&gt; ['path/to/module/foo']
  }
}

This is the article about the detailed explanation of vue-property-decorator and vux-class in Vue decorator. For more related vue-property-decorator and vux-class content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!