在Vue中使用JavaScript
<script>
export default {
name: 'Types',
props: ['xxx'], //接收外部属性xxx
data() { //声明data
return {
type: '-'
}
},
mounted() {
console.log(this.xxx)
},
methods: { //方法
selectType(type) {
if (type !== '-' && type !== '+') {
throw new Error('type is unknown')
}
this.type = type
}
}
}
</script>
使用TypeScript(与JavaScript最大的区别是不用构造选项,构造选项没有类型,TS必须使用class)
npm i -S vue-property-decorator //安装 vue-property-decorator
<script lang="ts">
import Vue from 'vue';
import {Component} from 'vue-property-decorator'; //从vue-property-decorator引入Component装饰器
@Component //使用装饰器,作用告诉TypeScript这个东西是vue组件
export default class Types extends Vue { //导出一个class,名字是组件名,继承 Vue
type = '-'; //声明data,语法:任何的赋值语句,会变成实例的属性
selectType(type: string) { //methods方法,直接写函数就行,要声明data的类型
if (type !== '-' && type !== '+') {
throw new Error('type is unknown');
}
this.type = type;
}
}
</script>
总结
从vue-property-decorator 库里引入 Component 装饰器
把装饰器修饰到class上,作用是(type会自动处理为data,selectType处理为methods,按组件进行处理)
class可以声明 data methods 声明周期等等,注意data的类型
@Prop装饰器(告诉class这个类,后面这个属性不是data,不写@Prop就是data,写就是prop)
@Prop(options: (PropOptions | Constructor[] | Constructor) = {}) decorator
import { 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
}
propA //属性名
Number //propA运行时的类型
number | undefined; //propA编译时的类型
readonly //只读的,不能修改
this.propA //使用prop
声明prop时如果写了类型为undefined,在其它任何地方使用prop时,必须检查是不是undefined,否则会编译错误
mounted(){
if(this.propA === undefined){
console.log('undefined')
}else{
console.log(this.propA)
}
}
总结如何使用TypeScript声明一个vue组件
import {Component,Prop} from 'vue-property-decorator'; //引入装饰器
@Component //加上装饰器
export default class YourComponent extends Vue //声明一个继承vue的类
type = '-'; //声明data直接写
@Prop(Number) xxx: number | undefined; //声明prop,运行和编译时的类型
@PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {}) decorator
@PropSync装饰器与@prop用法类似,区别在于:@PropSync 会生成一个新的计算属性
@PropSync接收两个参数:
propName: string // 表示父组件传递过来的属性名
options: Constructor | Constructor[] | PropOptions //与@Prop的第一个参数一致
import { Vue, Component, PropSync } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@PropSync('name', { type: String }) syncedName!: string
}
@PropSync需要配合父组件的.sync修饰符使用
@Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) decorator
@Model装饰器允许我们在一个组件上自定义v-model,接收两个参数:
event: string // 事件名
options: Constructor | Constructor[] | PropOptions //与@Prop的第一个参数一致
import { Vue, Component, Model } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@Model('change', { type: Boolean }) readonly checked!: boolean
}
@Watch(path: string, options: WatchOptions = {})
@Watch 装饰器接收两个参数:
path: string //被侦听的属性名
options //包含两个属性(immediate,deep)
immediate?:boolean //侦听开始之后是否立即调用该回调函数
deep?:boolean //被侦听的对象的属性被改变时,是否调用该回调函数
侦听开始,发生在beforeCreate勾子之后,created勾子之前
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) {}
}
@Emit(event?: string)
@Emit装饰器接收一个可选参数,该参数是$Emit的第一个参数,充当事件名
如果没有提供这个参数,$Emit会将回调函数名的camelCase转为kebab-case,并将其作为事件名
@Emit会将回调函数的返回值作为第二个参数,如果返回值是一个Promise对象
$emit会在Promise对象被标记为resolved之后触发
@Emit的回调函数的参数,会放在其返回值之后,一起被$emit当做参数使用
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)
})
}
}
@Ref(refKey?: string)
@Ref 装饰器接收一个可选参数,用来指向元素或子组件的引用信息
如果没有提供这个参数,会使用装饰器后面的属性名充当参数
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
}