我个人对更严格类型限制没有积极的看法,毕竟各类转类型的骚写法写习惯了。
然鹅最近的一个项目中,是Type+Vue,毛计喇,学之...…真香!
1.使用官方脚手架构建
新的VueCLI工具允许开发者使用Type集成环境创建新项目。
只需运行vuecreatemy-app。
然后,命令行会要求选择预设。使用箭头键选择Manuallyselectfeatures。
接下来,只需确保选择了Type和Babel选项,如下图:
完成此操作后,它会询问你是否要使用class-stylecomponentsyntax。
然后配置其余设置,使其看起来如下图所示。
VueCLI工具现在将安装所有依赖项并设置项目。
接下来就跑项目喇。
总之,先跑起来再说。
2.项目目录解析
通过tree指令查看目录结构后可发现其结构和正常构建的大有不同。
两句话概括:
此时我们打开亲切的src/components/HelloWorld.vue,将会发现写法已大有不同
至此,准备开启新的篇章Type极速入门和vue-property-decorator
##3.Type极速入门
3.1基本类型和扩展类型
Type与Java共享相同的基本类型,但有一些额外的类型。
想象元组作为有组织的数组,你需要以正确的顺序预定义数据类型。
如果不遵循为元组预设排序的索引规则,那么Type会警告。
(tuple第一项应为number类型)
2.枚举enum*
enum类型是对Java标准数据类型的一个补充。像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
另一个很好的例子是使用枚举来存储应用程序状态。
3.Void
在Type中,你必须在函数中定义返回类型。像这样:
若没有返回值,则会报错:
我们可以将其返回值定义为void:
此时将无法return
4.Any
Emmm...就是什么类型都行,当你无法确认在处理什么类型时可以用这个。
但要慎重使用,用多了就失去使用Ts的意义。
主要应用场景有:
用很粗浅的话来描述就是:"Never是你永远得不到的爸爸。"
具体的行为是:
3.类型断言
简略的定义是:可以用来手动指定一个值的类型。
有两种写法,尖括号和as:
使用例子有:
当Type不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
如果你访问长度将会报错,而有时候,我们确实需要在还不确定类型的时候就访问其中一个类型的属性或方法,此时需要断言才不会报错:
安全导航操作符(.)和空属性路径:为了解决导航时变量值为null时,页面运行时出错的问题。
非空断言操作符:
能确定变量值一定不为空时使用。
与安全导航操作符不同的是,非空断言操作符不会防止出现null或undefined。
软件工程的一个主要部分就是构建组件,构建的组件不仅需要具有明确的定义和统一的接口,同时也需要组件可复用。支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性。
在C#和Java中,可以使用"泛型"来创建可复用的组件,并且组件可支持多种数据类型。这样便可以让用户根据自己的数据类型来使用组件。
1.泛型方法
调用方式也有两种:
Ts的特殊类型Any在具体使用时,可以代替任意类型,咋一看两者好像没啥区别,其实不然:
泛型接口:
Interface,国内翻译成接口。
Typealias,类型别名。
以下内容来自:
Type中的interface和type到底有什么区别
都可以用来描述一个对象或函数:
都允许拓展(extends):
interface和type都可以拓展,并且两者并不是相互独立的,也就是说interface可以extendstype,type也可以extendsinterface。虽然效果差不多,但是两者语法不同。
interfaceextendsinterface
typeextendstype
interfaceextendstype
typeextendsinterface
type可以而interface不行
interface可以而type不行
interface有可选属性和只读属性
上面的例子说明,当完成User对象的初始化后loginName就不可以修改了。
3.4实现与继承:implementsvsextends
extends很明显就是ES6里面的类继承,那么implement又是做什么的呢?它和extends有什么不同?
implement,实现。与C#或Java里接口的基本作用一样,Type也能够用它来明确的强制一个类去符合某种契约
implement基本用法:
而extends是继承父类,两者其实可以混着用:
搭配interface和type的用法有:
前面我们讲到Vue项目中的shims-tsx.d.ts和shims-vue.d.ts,其初始内容是这样的:
这里列举出几个常用的:
namespace:“内部模块”现在称做“命名空间”
moduleX{相当于现在推荐的写法namespaceX{)
跟其他JS库协同
所以上述两个文件:
其实很好理解:
protected和private类似,但是,protected成员在派生类中可以访问
从vue2.5之后,vue对ts有更好的支持。根据官方文档,vue结合type,有两种书写方式
Vue.extend
理想情况下,Vue.extend的书写方式,是学习成本最低的。在现有写法的基础上,几乎0成本的迁移。
但是Vue.extend模式,需要与mixins结合使用。在mixin中定义的方法,不会被type识别到
,这就意味着会出现丢失代码提示、类型检查、编译报错等问题。
菜鸟才做选择,大佬都挑最好的。直接讲第二种吧:
4.1vue-class-component
我们回到src/components/HelloWorld.vue
有写过python的同学应该会发现似曾相识:
“@”,与其说是修饰函数倒不如说是引用、调用它修饰的函数。
或者用句大白话描述:@:"下面的被我包围了。"
举个栗子,下面的一段代码,里面两个函数,没有被调用,也会有输出结果:
直接运行,输出结果:
上面代码可以看出来:
但是,解释器读到函数修饰符“@”的时候,后面步骤会是这样:
换言之,修饰符带的那个函数的入口参数,就是下面的那个整个的函数。有点儿类似JavaScript里面的functiona(function{...});
2.vue-property-decorator和vuex-class提供的装饰器
vue-property-decorator的装饰器:
vuex-class的装饰器:
我们拿原始Vue组件模版来看:
以上模版替换成修饰符写法则是:
正如你所看到的,我们在生命周期列表那都添加privateXXXX方法,因为这不应该公开给其他组件。
而不对method做私有约束的原因是,可能会用到@Emit来向父组件传递信息。
4.2添加全局工具
引入全局模块,需要改main.ts:
npmiVueI18n
但仅仅这样,还不够。你需要动src/vue-shim.d.ts:
之后使用this.$i18n的话就不会报错了。
4.3Axios使用与封装1.新建文件request.ts
文件目录:
为了方便,我们还需要定义一套固定的axios返回的格式,新建ajax.ts: