vue-property-decorator分享
关于vue-property-decorator的疑问
vue-property-decorator是什么
- 'vue-property-decorator' 是vue社区推出的用于拓展 'vue-class-component' 的 装饰器集合库
vue-class-component是什么
- 'vue-class-component' 是vue官方推出的一个库,可让您使用类样式的语法来制作Vue组件,使vue组件可以使用继承(Extend)、混入(Mixins)等高级特性
装饰器是什么
- 装饰器(Decorator)是一种与类(class)相关的语法,用来注释或修改类和类方法,许多面向对象的语言都有这项功能。
- 装饰器是一种函数,写成
@ + 函数名
。它可以放在类和类方法的定义前面。
vue-property-decorator的用法
vue-property-decorator有哪些内容
- @Component
- @Prop
- @PropSync
- @Model
- @Watch
- @Emit
- @Ref
- @Provide
- @Inject
- @ProvideReactive
- @InjectReactive
@Component
- 继承自vue-class-component
- 其中可以声明props,watch,components,template
- 采用vue-property-decorator后尽量将components,template以外的内容用装饰器声明
- 例:
@Component({
template: '<button @click="onClick">Click!</button>',
components: {
helloworld,
}
})
@Prop
@Prop([String, Boolean]) readonly propA: string | boolean | undefined
@Prop() title?: string;
相当于
props: {
propC: {
type: [String, Boolean],
},
title: {
}
}
@PropSync
- 组件的props值之一,并给此prop添加一个<kbd>.sync</kbd>修饰符
- 例:
@PropSync('name', { type: String }) syncedName!: string
相当于
props: {
name: {
type: String
}
},
computed: {
syncedName: {
get() {
return this.name
},
set(value) {
this.$emit('update:name', value)
}
}
}
@Model
- 组件的v-model, 用于给自定义组件添加v-model
- 例:
@Model('change', { type: Boolean }) readonly checked!: boolean
相当于
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: {
type: Boolean
}
}
@Watch
@Watch('child', {immediate: true, deep: true})
onChildChanged(val: string, oldVal: string) {}
相当于
watch: {
child: [{
handler: 'onChildChanged',
immediate: true,
deep: true
}]
},
methods: {
onChildChanged(val, oldVal) {}
}
@Emit
- 在函数的最后使用emit事件名
- 例:
count = 0
@Emit()
addToCount(n: number) {
this.count += n
},
@Emit('reset')
resetCount() {
this.count = 0
}
相当于
data() {
return {
count: 0
}
},
methods: {
addToCount(n) {
this.count += n
this.$emit('add-to-count', n)
},
resetCount() {
this.count = 0
this.$emit('reset')
},
}
@Ref
- refs值之一,第一个参数是ref值,此装饰器会将ref映射到计算属性中
- 例:
@Ref() readonly anotherComponent!: AnotherComponent
@Ref('aButton') readonly button!: HTMLButtonElement
相当于
computed() {
anotherComponent: {
cache: false,
get() {
return this.$refs.anotherComponent as AnotherComponent
}
},
button: {
cache: false,
get() {
return this.$refs.aButton as HTMLButtonElement
}
}
}
@Provide
- 等同于provide,用于祖孙组件的传输值,需要与inject配合使用
- 例:
@Provide() foo = 'foo'
@Provide('bar') baz = 'bar'
相当于
provide() { // 当前组件传入子孙组件的值
return {
foo: this.foo,
bar: this.baz
}
}
@Inject
- 等同于inject,用于祖孙组件的接收值,需要与provide配合使用
- 例:
@Inject('bar') readonly bar!: string
@Inject({ from: 'optional', default: 'default' }) readonly optional!: string
相当于
inject: { // 接收父、祖组件的 provide
bar: 'bar',
optional: { from: 'optional', default: 'default' },
},
@ProvideReactive 与 @InjectReactive
- 等同于provide/inject,用于祖孙组件的传输接收
- 与@Provide/inject不同的是,@ProvideReactive/@InjectReactive是响应式的, 使用后者的情况下,祖父组件进行修改时孙子组件会相应的变更
- 例:
@Component
class ParentComponent extends Vue {
@ProvideReactive() one = 'value'
}
@Component
class ChildComponent extends Vue {
@InjectReactive() one!: string
}
相当于
inject: { // 接收父、祖组件的 provide
one: 'foo',
},
data() {
return {
one: 'foo',
}
},
provide() { // 当前组件传入子孙组件的值
return {
one: this.one,
}
}
vue-property-decorator的其他用法
Component.registerHooks
- 此方法可用于vue生态下的其他钩子,例如vue-router
- 这些钩子不会被视为vue methods下的方法
- 用法:
Component.registerHooks([
'beforeRouteEnter',
'beforeRouteLeave',
'beforeRouteUpdate'
])
@Component
export default class HelloWorld extends Vue {
beforeRouteEnter(to, from, next) {...}
}
createDecorator
- 用此方法可以创建自定义的装饰器, 自定义装饰器的用法与es6中规定的装饰器一致。
- 用法:
import Vue from 'vue'
import Component,{ createDecorator } from 'vue-class-component'
const Log = createDecorator((options, key) => {
const originalMethod = options.methods[key]
options.methods[key] = function wrapperMethod(...args) {
console.log(`Invoked: ${key}(`, ...args, ')')
originalMethod.apply(this, args)
}
})
@Component
class MyComp extends Vue {
@Log
hello(value) {
// ...
}
}
与vue-property-decorator相关的一些内容
vuex-class
import { Component, Inject, Provide, Vue } from 'vue-property-decorator'
import {
State,
Getter,
Action,
Mutation,
namespace
} from 'vuex-class'
const someModule = namespace('path/to/module')
@Component
export class MyComp extends Vue {
@State('foo') stateFoo
@State(state => state.bar) stateBar
@Getter('foo') getterFoo
@Action('foo') actionFoo
@Mutation('foo') mutationFoo
@someModule.Getter('foo') moduleGetterFoo
// If the argument is omitted, use the property name 如果省略了参数,则使用属性名
// for each state/getter/action/mutation type
@State foo
@Getter bar
@Action baz
@Mutation qux
created () {
this.stateFoo // -> store.state.foo
this.stateBar // -> store.state.bar
this.getterFoo // -> store.getters.foo
this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true })
this.moduleGetterFoo // -> store.getters['path/to/module/foo']
}
}