持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
前言
阅读这篇文章将学习到:
- vue-property-decorator的用法
- 装饰器模式的运用
- 父子组件传值和Computed的灵活搭配
前面我们讲过了vue-class-component的写法,搭配着class组件我们还需要学习属性装饰器,vue-property-decorator,利用这个装饰器我们能够简化大部分的操作;
@Prop装饰器
@Prop的参数类型为:
export interface PropOptions<T=any> {
type?: PropType<T>;
required?: boolean;
default?: T | null | undefined | (() => T | null | undefined);
validator?(value: T): boolean;
}
也就是说我们在用这个参数和我们写props对象是一样,属性都是相同的,而且还有属性提示;唯一不同的在后面,就是我们这里会产生两个类型系统,一个是vue的类型系统一个是ts的类型系统,前面的是vue类型系统后面是ts类型系统,vue的类型系统是在vue运行时给组件进行type check的,而这里的ts类型仅仅只能对我们的编码进行智能提示,其实两者结合才是一个完整的ts check
@Prop({type:Object}) propName!:object;
但是如果任何情况下我们都要写两份类型这未免太麻烦了;但是框架设计者已经考虑到这一点,简单数据类型我们可以直接在ts类型中声明不需要另写一份,vue也会进行type check
@Prop() propName!:string;
@Prop() propName!:number;
@Prop() propName!:boolean;
但是如果我们不写任何类型那么type check就是object类型,如果传其他类型则会进行错误提示
@Prop() propName;
@PropSync装饰器
@PropSync装饰器类似于v-bind.sync
,主要用于子组件修改父组件传过来的值,它们的区别是什么?看下面的案例:
@PropSync('name', { type: String }) syncedName!: string
// 直接这样赋值就能修改父组件传递的props
this.syncedName = 'changed'
// 父组件
<A :propValue.sync="value"/>
// A组件需要通过methods去更新父组件这个value值
@Prop() propValue
click(){
this.$emit('update:propValue', NaN)
}
实际上@PropSync借用了一个Computed将这个修改父组件值得methods封装起来了,使得我们“不知庐山真面目”;
其实就是定义了一个“syncedName”的Computed,它的get访问器返回“this.name”,然后set访问器去通知父组件更新这个name
@Emit
这是最难理解的一个装饰器了,因为它里面有很多“潜规则”
子组件与父组件通信的方法:this.$emit(EventName,...args)
@Emit的写法
@Emit('add')
addOne(n){
this.count += n
return n+this.count
}
先把结论抛出来:
- Emit函数的参数是事件名称
- methods的参数是$emit传递的数据;但是如果遇到返回值会放在返回值后面
- 函数的返回值作为$emit传递的数据中第一个参数
- 函数返回一个promise,那么会把promise resolve之后的值作为传递的数据
再来思考我们上面写的代码,你能够一口气把它转化为我们平时写的vue代码吗?
addOne(n){
this.count+=n
this.$emit('add',n+this.count,n)
}
是不是足够复杂??但是如果记住上面的铁律,那么一切都解决了
@VModel
有这样一个需求:需要v-model绑定一个父组件传递过来的参数,该怎么办呢?
我们需要借助Computed来实现,在get访问器中返回这个props,然后在set访问器将新的值传递给父组件
@Prop() private readonly value;
public get inputValue(): void {
return this.value
}
public set inputValue(val) {
this.$emit('input',val)
}
@Ref
我们在操作Dom的时候经常需要使用到ref;但是如果每次都使用“this.$refs.xxx”显然不太方便,我们可以使用@Ref,它像等于将这个dom节点存储到Computed中
这样使用还有一个好处可以标注dom元素的类型,使用的时候有智能提示,非常友好,不用每次as any了!
@Ref('myButton') readonly button!:HTMLButtonElement;
// 等同于
get button(){
return this.$refs.myButton as HTMLButtonElement
}
总结:今天我们梳理了一下vue-property-decorator的用法,简化了我们的类组件;后续我们讲解一下vuex的类的写法,欢迎阅读