之前说到了vue的组件如果换用TypeScript环境,各个选项模块声明方法也有所变化,已经说明了data,methods,computed选项属性,这里继续列举说明。
另外,补充说明一点,vue中data选项在JS中的一般写法为函数形式:data(){return{}}。这种写法的好处是可以避免在复用组件时,发生多组件共用data数据库,数据的污染和混淆。每次return都会在该组件内生成一个独立空间存储数据,避免混用。之前提到,在TS中data可以直接使用定义变量的形式声明,我一开始也有疑惑会不会相当于是没有使用return形式的data,结果查阅一些资料,证明了TypeScript中变量形式的声明就相当于是return{}函数返回值,不需要担心数据污染问题,书写也很简洁了。
props写法该组件在父组件模板中如:
<name-listmsg="小李">接受父组件传递的props:
exportdefaultclassNameListextendsVue{@Prop({default:""})readonlymsg!:string;}在TypeScript中,!:表示一定存在,?:表示可能不存在。这两种在语法上叫赋值断言,是TS中非常重要的语法。
需要注意的是,@Prop()的括号内只允许接受一个参数,如果要输入多个参数,需要包裹成一个对象。
prop可以接受的参数如下:
@Prop(options:(PropOptions|Constructor[]|Constructor)={})
PropOptions,可以使用以下选项:type,default,required,validator
Constructor[],指定prop的可选类型
Constructor,例如String,Number,Boolean等,指定prop的类型
watch写法监听方法watch的写法就复杂一些,需要注意一下:
属性参数@Watch(path:string,options:WatchOptions={})
options包含两个属性immediate?:boolean侦听开始之后是否立即调用该回调函数;deep?:boolean被侦听的对象的属性被改变时,不论其被嵌套多深,调用该回调函数,即深度监听。
options的两个属性不写默认为false
watch声明写法,函数和参数分为两部分,函数名必须是on[key]Change这种形式。
@Watch('arr',{immediate:true,deep:true})onNameChanged(newValue:string[],oldValue:string[]){}可以接受旧值和新值并执行回调函数。
如:
exportdefaultclassNameListextendsVue{@Watch("name",{immediate:true,deep:true})privateonNameChange(newValue:string,oldValue:string){console.log("watch",newValue,oldValue);}}生命周期函数写法exportdefaultclassHelloWorldextendsVue{//created生命周期函数publiccreated():void{}//mounted生命周期函数publicmounted():void{}}写法跟在JS中一模一样,没什么需要好说的。
顺带提一句,在TS中,类中方法的修饰符默认就是public,声明可以被他人调用。
Ref写法属性参数:@Ref(refKey?:string)
@Ref装饰器接收一个可选参数,用来指向元素或子组件的引用信息。如果没有提供这个参数,会使用装饰器后面的属性名充当参数。
<HelloWorldref="addButton"></HelloWorld>import{Component,Vue,Ref}from'vue-property-decorator';importHelloWorldfrom"@/components/HelloWorld.vue";@Component({components:{HelloWorld}})exportdefaultclassAppextendsVue{@Ref('RefComponent')readonlyref!:HTMLDocument;getRef(){this.$refs.RefComponent.mothed();//mothed为子组件中定义的方法}}emit写法emit的写法也比较复杂一点。
属性参数:@Emit(event?:string)参数说明:
@Emit装饰器接收一个可选参数,充当事件名。如果没有提供这个参数,@Emit会将回调函数名的camelCase转为kebab-case,并将其作为事件名
@Emit会将回调函数的返回值作为第二个参数,如果返回值是一个Promise对象,$emit会在Promise对象被标记为resolved之后触发。
@Emit的回调函数的参数,会在回调函数没有返回值的情况下,被$emit当做第二个参数使用;有返回值,会放在其返回值之后,一起被$emit当做参数使用
//当前子组件<div@click="clickMsg"/>//相当于JS写法的clickMsg(){this.$emit('change-msg','jack');}//父组件中<hello-world:msg="msg"@change-msg="handleChangeMsg"/>handleChangeMsg(value){this.msg=value}//TS写法父组件一致,只是子组件的区别import{Component,Prop,Emit}from'vue-property-decorator';exportdefaultclassHelloWorldextendsVue{@Emit("change-msg")clickMsg(){//$emit的第二个参数,也就是给父组件的值return"jack";}}比较绕,写几个例子试验下就清晰了。实际上不适用这种写法,使用传统的$emit也是没问题的。
@Model(V-Model)默认情况下,一个组件上的v-model?会把?value用作?prop,并把?input用作?event,但是一些输入类型比如单选框和复选框按钮可能想使用不同的?valueprop组合来达到不同的目的。使用model选项可以回避这些情况产生的冲突。
下面是Vue官网的例子:
Vue.component('base-checkbox',{model:{prop:'checked',event:'change'},props:{checked:Boolean},template:`<inputtype="checkbox"v-bind:checked="checked"v-on:change="$emit('change',$event.target.checked)">`})在这个组件上使用?v-model?的时候:
<base-checkboxv-model="lovingVue"></base-checkbox>注意:你仍然需要在组件的props选项里声明checked这个prop。
使用vue-property-decorator提供的@Model改造上面的例子,在自定义组件中:
import{Component,Prop,Model}from'vue-property-decorator';exportdefaultclassBaseCheckboxextendsVue{@Model('change',{type:Boolean})checked!:boolean;}mixin混入在TypeScript中写mixin,mixin本身是个.ts文件,需要注意。然后在文件内部通过export来进行类的导出,然后在vue文件中引入得到抽离出来的公共部分。
MyMixin.ts写法:
exportdefaultclassNameListextendsVue{@Prop({default:""})readonlymsg!:string;}0使用mixins的文件:
exportdefaultclassNameListextendsVue{@Prop({default:""})readonlymsg!:string;}1需要写两个或更多mixins的话,在Mixins里面继续添加即可。通过Mixins引入可以正常使用TS的语法检测系统,用起来也不复杂。
常用的组件声明就这些,先分享这么多,如有更多内容未来补充。
原文:https://juejin.cn/post/7098356360416837668本文如未解决您的问题请添加抖音号:51dongshi(抖音搜索懂视),直接咨询即可。