須要用到vue-property-decorator
這個庫前端
npm i -S vue-property-decorator
有幾個修飾其和1個function(Mixin):vue
@Prop
@PropSync
@Model
@Watch
@Provide
@Inject
@ProvideReactive
@InjectReactive
@Emit
@Ref
@Component
(provided by vue-class-component)Mixins
(the helper function named mixins
provided by vue-class-component)vuex-classreact
@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 }
等同於git
export default { props: { propA: { type: Number }, propB: { default: 'default value' }, propC: { type: [String, Boolean] } } }
提醒:github
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'
.vuex
@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 }
等同於npm
export default { props: { name: { type: String } }, computed: { syncedName: { get() { return this.name }, set(value) { this.$emit('update:name', value) } } } }
Other than that it works just like @Prop
other than it takes the propName as an argument of the decorator, in addition to it creates a computed getter and setter behind the scenes. This way you can interface with the property as it was a regular data property whilst making it as easy as appending the .sync
modifier in the parent component.promise
@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 }
等同於bash
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
.app
@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) {} }
等同於
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' }
等同於
const symbol = Symbol('baz') export const MyComponent = Vue.extend({ inject: { foo: 'foo', bar: 'bar', optional: { from: 'optional', default: 'default' }, [symbol]: 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) }) } }
等同於
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 }
等同於
export default { computed() { anotherComponent: { cache: false, get() { return this.$refs.anotherComponent as AnotherComponent } }, button: { cache: false, get() { return this.$refs.aButton as HTMLButtonElement } } } }
關注的個人公衆號不按期分享前端知識,與您一塊兒進步!