前言:
vue 中使用 typescript的 class-style 风格代码,除了用到ts的语法,还用到了 vue-property-decorator语法 vue-class-component语法
vue-property-decorator 与 vue-class-component 的关系
vue class component 是vue 官方出的
vue property decorator 是社区出的
其中vue class component 提供了 vue component 等等
vue property decorator 深度依赖了 vue class component 拓展出了很多操作符 @Prop @Emit @Inject 等等 可以说是 vue class component 的一个超集
正常开发的时候 你只需要使用 vue property decorator 中提供的操作符即可 不用再从vue class componen 引入vue component
一、如何使用(官网介绍)
1、导入npm 包
npm i -S vue-property-decorator
主要有以下一些装饰器和一个方法
@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)
@Component
注: 该属性完全继承于vue-class-component
属性参数:@Component(options: ComponentOptions = {})
参数说明:@Component 装饰器可以接收一个对象作为参数,可以在对象中声明 components ,filters,directives, beforeRouteLeave等未提供装饰器的选项,也可以声明computed,watch等
<template>
<div class="parent">
parent组件--{{title}}
<hr>
<Home v-model="title"></Home>
<About v-model="title"></About>
</div>
</template>
1、js 写法
<script>
import Home from './Home.vue'
import About from './About.vue'
export default {
data() {
return {
title: '父组件中的值'
}
},
components: {
Home,
About
}
}
</script>
2、ts 写法
<script lang='ts'>
import Home from './Home.vue'
import About from './About.vue'
import { Component, Vue } from 'vue-property-decorator';
@Component({
components: {
Home,
About
}
})
export default class extends Vue {
private title: string = '父组件中的值'
}
</script>
@Emit
属性参数:@Emit(event?: string)
参数说明:
@Emit 装饰器接收一个可选参数,充当事件名。如果没有提供这个参数,@Emit会将回调函数名的camelCase转为kebab-case,并将其作为事件名;
@Emit的回调函数的参数,会在回调函数没有返回值的情况下,被$emit当做第二个参数使用。
@Emit会将回调函数的返回值作为第二个参数,如果返回值是一个Promise对象,$emit会在Promise对象被标记为resolved之后触发;
<template>
<div class="home">
vue+ts项目vue-property-decorator用法
<hr>
<button @click="triggerEmit('qqq')">触发emit</button>
</div>
</template>
1、js写法
export default {
data() {
return {}
},
mounted() {
this.$on('trigger-emit', data => {
alert(data)
})
},
methods: {
triggerEmit(val) {
this.$emit('trigger-emit', val)
}
}
}
2、ts写法
<script lang="ts">
import { Component, Vue, Emit } from 'vue-property-decorator';
@Component({})
export default class Home extends Vue {
private mounted() {
this.$on('demo-log', (data: any): void => {
alert(data)
})
}
@Emit('demo-log')
triggerEmit(n: any) {
console.log('hhh')
}
}
</script>
另一种写法,$on位置使用 - 链接,@Emit位置直接使用驼峰命名,则可以省略括号中的名称:”
export default class Home extends Vue {
private mounted() {
this.$on('trigger-emit', (data: any): void => {
alert(data)
})
}
@Emit()
triggerEmit(n: any) {
console.log('hhh')
}
}
案例二、
ts
<script lang="ts">
import {Vue, Component, Emit} from 'vue-property-decorator';
@Component
export default class "组件名" extends Vue{
mounted(){
this.$on('emit-todo', function(n) {
console.log(n)
})
this.emitTodo('world');
}
@Emit()
emitTodo(n: string){
console.log('hello');
}
}
</script>
以上代码会输出 hello world,js写法如下
<script>
import Vue from 'vue';
export default {
mounted(){
this.$on('emit-todo', function(n) {
console.log(n)
})
this.emitTodo('world');
},
methods: {
emitTodo(n){
console.log('hello');
this.$emit('emit-todo', n);
}
}
}
</script>
在@Emit装饰器的函数会在运行之后触发等同于其函数名(驼峰式会转为横杠式写法)的事件, 并将其参数传递给$emit.
如果我们想触发特定的事件呢,比如在emitTodo下触发reset事件:
<script lang="ts">
import {Vue, Component, Emit} from 'vue-property-decorator';
@Component
export default class "组件名" extends Vue{
@Emit('reset')
emitTodo(n: string){
}
}
</script>
我们只需要给装饰器@Emit传递一个事件名参数reset,这样函数emitTodo运行之后就会触发reset事件.
@Prop
属性参数:@Prop(options: (PropOptions | Constructor[] | Constructor) = {})
参数说明:@Prop装饰器接收一个参数,这个参数可以有三种写法:
PropOptions,可以使用以下选项:type,default,required,validator;
Constructor[],指定 prop 的可选类型;
Constructor,例如String,Number,Boolean等,指定 prop 的类型;
注意:
属性的ts类型后面需要加上undefined类型;或者在属性名后面加上!,表示非null 和 非undefined的断言,告诉TypeScript我这里一定有值,否则编译器会给出错误提示;
!: 表示一定存在,?: 表示可能不存在。这两种在语法上叫赋值断言
比如子组件从父组件接收三个属性propA,propB,propC
propA类型为Number
propB默认值为default value
propC类型为String或者Boolean
export default {
props: {
propA: {
type: Number
},
propB: {
default: 'default value'
},
propC: {
type: [String, Boolean]
},
}
}
使用vue-property-decorator提供的@Prop可以将上面的代码改造为如下:
<script lang="ts">
import {Vue, Component, Prop} from 'vue-property-decorator';
@Component
export default class "组件名" extends Vue{
@Prop(Number) propA!: number;
@Prop({default: 'default value'}) propB!: string;
@prop([String, Boolean]) propC: string | boolean;
}
</script>
@Prop接受一个参数可以是类型变量或者对象或者数组.@Prop接受的类型比如Number是JavaScript的类型,之后定义的属性类型则是TypeScript的类型.
@Ref
属性参数:@Ref(refKey?: string)
参数说明:@Ref 装饰器接收一个可选参数,用来指向元素或子组件的引用信息。如果没有提供这个参数,会使用装饰器后面的属性名充当参数