Vue 的这些装饰器,你还不会?(2)
Vue Property Decorator
Github 地址:Vue Property Decorator
Vue Property Decorator提供了一些装饰器,包括@Prop、@Watch、@Emit、@Inject、@Provide、@Model等等。这些装饰器可以帮助你更方便地定义组件的属性、监听属性的变化、触发事件、注入依赖、提供依赖等等。
下载
npm i -S vue-property-decorator
使用
Prop
使用 Prop 可以快速地让你设置你的传入属性。
比如下面 propA,可以设置为只读,number 类型,下面的 propB,可以设置默认值
import { Vue, Component, Prop } from 'vue-property-decorator';
@Component
export default class MyComponent extends Vue {
@Prop(Number) readonly propA!: number;
@Prop({ default: 'default value' }) readonly propB!: string;
// 这行代码使用了@Prop装饰器来定义一个名为propC的属性,并指定了它的类型为string或boolean。
// [String, Boolean]是一个数组,表示propC可以是string类型或boolean类型。readonly表示这个属性是只读的,不能在组件内部修改它的值。
// propC: string | boolean
// 表示这个属性的类型是string或boolean,也就是说,它的值可以是string类型或boolean类型。
// 这样定义propC的好处是,当propC被传入组件时,Vue会自动根据它的类型进行类型检查,确保它的值符合预期。
@Prop([String, Boolean]) readonly propC: string | boolean;
}
等同于:
export default {
props: {
propA: {
type: Number,
},
propB: {
default: 'default value',
},
propC: {
type: [String, Boolean],
},
},
}
Watch
@Watch 装饰器可以用于类中的方法上,用于监听指定的数据变化。当被监听的数据发生变化时,这个方法就会被调用,并且会传入两个参数:新值和旧值。
例如,我们可以使用 @Watch 装饰器来监听 child 这个属性的变化,如下所示:
import { 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) {}
@Watch('person')
@Watch('child')
onPersonAndChildChanged() {}
}
相当于:
export default {
watch: {
child: [
{
handler: 'onChildChanged',
immediate: false,
deep: false,
},
{
handler: 'onPersonAndChildChanged',
immediate: false,
deep: false,
},
],
person: [
{
handler: 'onPersonChanged1',
immediate: true,
deep: true,
},
{
handler: 'onPersonChanged2',
immediate: false,
deep: false,
},
{
handler: 'onPersonAndChildChanged',
immediate: false,
deep: false,
},
],
},
methods: {
onChildChanged(val, oldVal) {},
onPersonChanged1(val, oldVal) {},
onPersonChanged2(val, oldVal) {},
onPersonAndChildChanged() {},
},
}
Emit
当一个 Vue 组件需要与其它组件进行通信时,可以使用 emit 方法来触发自定义事件。emit 方法接收两个参数:第一个参数是自定义事件的名称,第二个参数是传递给父组件的数据。
父组件可以通过 v-on 指令监听这个自定义事件,并且在父组件中定义一个方法来处理这个事件。在 vue-property-decorator 中,可以使用 @Emit 装饰器来定义组件的自定义事件。@Emit 装饰器可以用于方法上,将这个方法标记为组件的自定义事件。在这个方法中,可以通过 return 语句来返回需要传递给父组件的数据。例如:
import { Component, Vue, Emit } from 'vue-property-decorator';
@Component
export default class MyComponent extends Vue {
@Emit()
handleClick() {
return 'hello';
}
}
在这个例子中,我们定义了一个名为 handleClick 的方法,并且使用 @Emit 装饰器将它标记为组件的自定义事件。当这个方法被调用时,它会返回一个字符串 'hello',这个字符串会被传递给父组件。在父组件中,可以使用 v-on 指令来监听这个自定义事件,并且在父组件中定义一个方法来处理这个事件。例如:
<template>
<div>
<my-component @click="handleClick"></my-component>
</div>
</template>
<script>
import MyComponent from './MyComponent.vue';
export default {
components: {
MyComponent,
},
methods: {
handleClick(data) {
console.log(data); // 输出 'hello'
},
},
};
</script>
在这个例子中,我们在父组件中使用 @click 指令来监听 MyComponent 组件的自定义事件,并且在父组件中定义了一个名为 handleClick 的方法来处理这个事件。当 MyComponent 组件触发自定义事件时,这个事件会被传递给父组件的 handleClick 方法,并且传递的数据是 'hello'。
更普遍的用法:
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
@Ref 是用来获取其他组件的 Ref 的,比如我们像如下使用,对于第一个 @Ref() readonly anotherComponent!: AnotherComponent
,我们的含义是这个ref
是只读的,并且是从this.$refs
的anotherComponet
上拿到的值,而@Ref('aButton') readonly button!: HTMLButtonElement
,则是制定了我们的this.$refs
后面的访问值为aButton
。
例子:
import { 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
}
}
}
}
本篇文章就到这里啦~
下一篇文章我将详细讲讲装饰器的原理
求一个赞~
转载自:https://juejin.cn/post/7251501945273729084