背景
最近公司开发了一个新项目,于是和大家一起商量了一下,是否要在Vue中使用一下TS,大家一致同意(可能是TS的魔力所在),于是志气昂扬的将我们之前的旧项目结构造成成了TS结构(目前代理还有问题,惭愧),在讲述TS之前,我想先讲一下我理解的TS。
Javascript自创建开始一直是以动态类型语言自居,在使用和开发上大大加强了灵活性,但是灵活性的背后同时增加了代码的混乱、结构不清晰。很多错误我们在运行阶段,才得以发现。前同事留下的代码,我们需要大量阅读实现才知道这个函数(或者类,本质上也是函数)具体是干嘛的。那TS究竟解决了什么问题,让现在的前端为之疯狂,我认为有两个原因
1、声明式类型和类型推断,在我们开发过程中,我们需要显示声明每一个值对象的类型,这样TS通过词法语法分析后能建立起来一个扫描机制,帮助我们在静态代码编写时发现错误(关注一下词法作用域哦,它也是静态的)
2、这个也是认为最重要的,就是定义和实现分离。我们上面说过,为了搞懂一段代码我们需要大量反复的读代码的具体实现,那么为什么不将一个接口抽离出来,基于这个接口做实现呢,TS帮我们做到了,我们现在不需要再去关注代码内部的具体实现,简单看一下接口,就已经知道代码块的主要功能和作用。这个就是我们常说的基于接口编程而非实现。
在这里我再补充一下,Vue的源码实现中使用到了继承,我们所使用的所有组件都是继承自Vue这个类,包括Vue的原型方法和静态方法。这样保证了每个组件的唯一性。这里我们就可以看到,我们虽然平常在写面向过程代码,但是框架已经帮助我们转向了面向对象风格的代码。
但是我们在面向对象中,经常听到一句话,多用组合少用继承。我对这个感触较多,我们在开Vue对的大型项目时,有时候为了做到精准更新(让响应式系统只收集当前组件的watcher),将页面拆分的很碎,好处是更新代价小,缺点就是我们在查找组件时,链路太长,如果过程中还有层级属性传递,头大了。组合的出现就是为了解决集成所带来的的这个问题,我们可以看到Vue3.0中已经开始向Composition(组合)转变,,所以我们深入一点看,框架在变,设计原理其实一直是固定的。
我们知道目前主流的三种编程范式,面向对象、面向过程、函数式编程。在大家没有真正建立起来面向对象的整体概念时,我们其实都在写面向过程风格代码,至于面向过程和面向对象语言的定义,大家可以自行搜索。这里留一个问题,你认为Javascript是面向对象风格的语言吗?
装饰器
我们先来回顾一下ecma规范中的装饰器,关于详细用法,大家可以去看一下阮一峰老师的es6文档Decorator系列和TypeScript文档中的Decorator系列,比较全面。装饰器的规范目前还没有定案,先来看一下已有的装饰器用法。
装饰类
上面的示例,我们装饰了一个类,装饰器本身就是一个函数实现,在装饰类的情况下,只会有构造函数一个参数,并且不能在装饰的情况下传参,注意执行顺序是自下向上的,也就是先执行role,再执行log。
装饰属性和方法
装饰参数
装饰器原理
我们直接看ts编译后的结果,一起揭开装饰器的神秘面纱
上面的代码是ts编译后,比较复杂,我们简化一下,看一下简化后的
类、属性、参数装饰器原理
上面基本上就是一些装饰器的知识了,我们接下来去看一下vue的ts是怎么实现的,想要了解vue的ts装饰器,我们需要了解两个类库,一个是vue-class-component,另一个是vue-property-decorator,我们接下来先来看vue-class-component,gogogo出发。
vue-class-component
我们先来回忆一下是如何使用vue的ts语法的
import {Component, Vue} from 'vue-property-decorator'
export default class extends Vue {}
如果你按照上面的写法,你的脚本百分百是会报错滴,vue会提示你提供的组件配置参数缺少render或者template模板,主要是因为忘记把Component装饰器用上了,我们调整一下
import {Component, Vue} from 'vue-property-decorator'
@Component
export default class extends Vue {}
OK,到此为止,一个Vue的组件创建完成了,我们也就迎来了vue装饰器的第一位猪脚,也是最重要的一个装饰器,没有唯一,因为它是所有装饰器的容器,废话少说,直接上代码
Component内部指向了componentFactory函数,让我们继续勒死狗
vue-property-decorator
vue-property-decorator是基于Component.__decorators__进行的二次封装,主要提供了Prop、Watch、Model、Inject、Provide、Ref等装饰器,我们来看一下Prop,剩下的大家可以自行查看
@Prop
我们看到装饰器内部有一个createDecorator函数,它会自动将回调函数注入到当前类的装饰器集合中,在Component中被整体调用,调用时,将key合并到options的props中,有了前面的装饰器的知识,现在再来看这些是不是很简单,这里我们唯一要注意的就是reflect-metadata,这是一个修饰元数据的类库,可以通过对数据的数据进行定义,来做一些其他操作,大家可以下去自行搜索了解,在vue-property-decorator中,有两类装饰器用到了metadata,Prop和Model。
总结
时间比较紧,花了2个小时将这些知识汇总了一下,过程难免疏漏,大家共勉!