内容简介:我个人对更严格类型限制没有积极的看法,毕竟各类转类型的骚写法写习惯了。然鹅最近的一个项目中,是
前言
我个人对更严格类型限制没有积极的看法,毕竟各类转类型的骚写法写习惯了。
然鹅最近的一个项目中,是 TypeScript
+ Vue
,毛计喇,学之...…真香!
1. 使用官方脚手架构建
新的 VueCLI
工具允许开发者 使用 TypeScript
集成环境 创建新项目。
只需运行 vue createmy-app
。
然后,命令行会要求选择预设。使用箭头键选择 Manuallyselectfeatures
。
接下来,只需确保选择了 TypeScript
和 Babel
选项,如下图:
完成此操作后,它会询问你是否要使用 class-style component syntax
。
然后配置其余设置,使其看起来如下图所示。
Vue CLI工具现在将安装所有依赖项并设置项目。
接下来就跑项目喇。
总之,先跑起来再说。
2. 项目目录解析
通过 tree
指令查看目录结构后可发现其结构和正常构建的大有不同。
这里主要关注 shims-tsx.d.ts
和 shims-vue.d.ts
两个文件
两句话概括:
-
shims-tsx.d.ts
,允许你以.tsx
结尾的文件,在Vue
项目中编写jsx
代码 -
shims-vue.d.ts
主要用于TypeScript
识别.vue
文件,Ts
默认并不支持导入vue
文件,这个文件告诉ts
导入.vue
文件都按VueConstructor<Vue>
处理。
此时我们打开亲切的 src/components/HelloWorld.vue
,将会发现写法已大有不同
至此,准备开启新的篇章 TypeScript
极速入门 和 vue-property-decorator
## 3. TypeScript
极速入门
3.1 基本类型和扩展类型
Typescript
与 Javascript
共享相同的基本类型,但有一些额外的类型。
-
元组
Tuple
-
枚举
enum
-
Any
与Void
1. 基本类型合集
2. 特殊类型
1. 元组 Tuple
想象 元组 作为有组织的数组,你需要以正确的顺序预定义数据类型。
如果不遵循 为元组 预设 排序 的索引规则,那么 Typescript
会警告。
( tuple
第一项应为 number
类型)
2. 枚举 enum
*
enum
类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
另一个很好的例子是使用枚举来存储应用程序状态。
3. Void
在 Typescript
中, 你必须在函数中定义返回类型 。像这样:
若没有返回值,则会报错:
我们可以将其返回值定义为 void
:
此时将无法 return
4. Any
Emmm...就是什么类型都行,当你无法确认在处理什么类型时可以用这个。
但要慎重使用,用多了就失去使用Ts的意义。
主要应用场景有:
-
接入第三方库
-
Ts菜逼前期都用
5. Never
用很粗浅的话来描述就是:" Never
是你永远得不到的爸爸。"
具体的行为是:
-
thrownewError(message)
-
returnerror("Something failed")
-
while(true){}// 存在无法达到的终点
3. 类型断言
简略的定义是:可以用来手动指定一个值的类型。
有两种写法,尖括号和 as
:
使用例子有:
当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
如果你访问长度将会报错,而有时候,我们确实需要在还不确定类型的时候就访问其中一个类型的属性或方法,此时需要断言才不会报错:
安全导航操作符 ( ?. )和非空断言操作符(!.)
安全导航操作符 ( ?. ) 和空属性路径:为了解决导航时变量值为null时,页面运行时出错的问题。
非空断言操作符:
能确定变量值一定不为空时使用。
与安全导航操作符不同的是,非空断言操作符不会防止出现 null 或 undefined。
3.2 泛型: Generics
软件工程的一个主要部分就是构建组件,构建的组件不仅需要具有明确的定义和统一的接口,同时也需要组件可复用。支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性。
在 C#
和 Java
中,可以使用"泛型"来创建可复用的组件,并且组件可支持多种数据类型。这样便可以让用户根据自己的数据类型来使用组件。
1. 泛型方法
在TypeScript里, 声明泛型方法 有以下两种方式:
调用方式也有两种:
2. 泛型与 Any
Ts
的特殊类型 Any
在具体使用时,可以代替任意类型,咋一看两者好像没啥区别,其实不然:
-
方法一,打印了
arg
参数的length
属性。因为any
可以代替任意类型,所以该方法在传入参数不是数组或者带有length
属性对象时,会抛出异常。 -
方法二,定义了参数类型是
Array
的泛型类型,肯定会有length
属性,所以不会抛出异常。
3. 泛型类型
泛型接口:
3.3 自定义类型: Interface
vs Typealias
Interface
,国内翻译成接口。
Typealias
,类型别名。
以下内容来自:
Typescript 中的 interface 和 type 到底有什么区别
1. 相同点
都可以用来描述一个对象或函数:
都允许拓展(extends):
interface
和 type
都可以拓展,并且两者并不是相互独立的,也就是说 interface
可以 extendstype
, type
也可以 extendsinterface
。 虽然效果差不多,但是两者语法不同 。
interface extends interface
type extends type
interface extends type
type extends interface
2. 不同点
type
可以而 interface
不行
-
type
可以声明基本类型别名,联合类型,元组等类型
-
type
语句中还可以使用typeof
获取实例的 类型进行赋值
-
其他骚操作
interface
可以而 type
不行
interface
能够声明合并
interface
有可选属性和只读属性
-
可选属性
接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 例如给函数传入的参数对象中只有部分属性赋值了。带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个
?
符号。如下所示
-
只读属性
顾名思义就是这个属性是不可写的,对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用
readonly
来指定只读属性,如下所示:
上面的例子说明,当完成User对象的初始化后loginName就不可以修改了。
3.4 实现与继承: implements
vs extends
extends
很明显就是ES6里面的类继承,那么 implement
又是做什么的呢?它和 extends
有什么不同?
implement
,实现。与C#或 Java 里接口的基本作用一样, TypeScript
也能够用它来明确的强制一个类去符合某种契约
implement基本用法:
而 extends
是继承父类,两者其实可以混着用:
搭配 interface
和 type
的用法有:
3.5 声明文件与命名空间: declare
和 namespace
前面我们讲到Vue项目中的 shims-tsx.d.ts
和 shims-vue.d.ts
,其初始内容是这样的:
declare
:当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
这里列举出几个常用的:
namespace
:“内部模块”现在称做“命名空间”
moduleX{
相当于现在推荐的写法 namespaceX{
)
跟其他 JS 库协同
类似模块,同样也可以通过为其他 JS 库使用了命名空间的库创建 .d.ts
文件的声明文件,如为 D3
JS 库,可以创建这样的声明文件:
所以上述两个文件:
-
shims-tsx.d.ts
, 在全局变量global
中批量命名了数个内部模块。 -
shims-vue.d.ts
,意思是告诉TypeScript
*.vue
后缀的文件可以交给vue
模块来处理。
3.6 访问修饰符: private
、 public
、 protected
其实很好理解:
-
默认为
public
-
当成员被标记为
private
时,它就不能在声明它的类的外部访问,比如:
protected
和 private
类似,但是, protected
成员在派生类中可以访问
4. Vue
组件的 Ts
写法
从 vue2.5 之后,vue 对 ts 有更好的支持。根据官方文档,vue 结合 typescript ,有两种书写方式
Vue.extend
vue-class-component
理想情况下, Vue.extend
的书写方式,是学习成本最低的。在现有写法的基础上,几乎 0 成本的迁移。
但是 Vue.extend
模式,需要与 mixins
结合使用。在 mixin 中定义的方法,不会被 typescript 识别到
,这就意味着会出现 丢失代码提示、类型检查、编译报错等问题。
菜鸟才做选择,大佬都挑最好的。直接讲第二种吧:
4.1 vue-class-component
我们回到 src/components/HelloWorld.vue
有写过 python
的同学应该会发现似曾相识:
-
vue-property-decorator
这个官方支持的库里,提供了函数 装饰器(修饰符) 语法
1. 函数修饰符 @
“@”,与其说是修饰函数倒不如说是引用、调用它修饰的函数。
或者用句大白话描述: @
: "下面的被我包围了。"
举个栗子,下面的一段代码,里面两个函数,没有被调用,也会有输出结果:
直接运行,输出结果:
上面代码可以看出来:
-
只定义了两个函数:
test
和func
,没有调用它们。 -
如果没有“@test”,运行应该是没有任何输出的。
但是,解释器读到函数修饰符“@”的时候,后面步骤会是这样:
-
去调用
test
函数,test
函数的入口参数就是那个叫“func
”的函数; -
test
函数被执行,入口参数的(也就是func
函数)会被调用(执行);
换言之,修饰符带的那个函数的入口参数,就是下面的那个整个的函数。有点儿类似 JavaScrip
t里面的 functiona(function(){...});
2. vue-property-decorator
和 vuex-class
提供的装饰器
vue-property-decorator
的装饰器:
-
@Prop
-
@PropSync
-
@Provide
-
@Model
-
@Watch
-
@Inject
-
@Provide
-
@Emit
-
@Component
( provided by vue-class-component) -
Mixins
(the helper function namedmixins
provided by vue-class-component)
vuex-class
的装饰器:
-
@State
-
@Getter
-
@Action
-
@Mutation
我们拿原始Vue组件模版来看:
以上模版替换成修饰符写法则是:
正如你所看到的,我们在生命周期 列表那都添加 privateXXXX
方法,因为这不应该公开给其他组件。
而不对 method
做私有约束的原因是,可能会用到 @Emit
来向父组件传递信息。
4.2 添加全局工具
引入全局模块,需要改 main.ts
:
npm iVueI18n
但仅仅这样,还不够。你需要动 src/vue-shim.d.ts
:
之后使用 this.$i18n()
的话就不会报错了。
4.3 Axios 使用与封装
1. 新建文件 request.ts
文件目录:
2. request.ts
文件解析
为了方便,我们还需要定义一套固定的 axios 返回的格式,新建 ajax.ts
:
3. main.ts
接口调用:
5. 编写一个组件
为了减少时间,我们来替换掉 src/components/HelloWorld.vue
,做一个博客帖子组件:
然后在 Home.vue
中使用:
这时候运行项目
这就是简单的父子组件
6. 参考文章
TypeScript — JavaScript with superpowers — Part II
VUE WITH TYPESCRIPT
TypeScript + 大型项目实战
Python修饰符 (一)—— 函数修饰符 “@”
Typescript 中的 interface 和 type到底有什么区别
作者掘金文章总集
需要转载到公众号的喊我加下白名单就行了。
-
「真®全栈之路」Web前端开发的后端指南
-
「Vue实践」5分钟撸一个Vue CLI 插件
-
「Vue实践」武装你的前端项目
-
「中高级前端面试」JavaScript手写代码无敌秘籍
-
「从源码中学习」面试官都不知道的Vue题目答案
-
「从源码中学习」Vue源码中的JS骚操作
-
「从源码中学习」彻底理解Vue选项Props
-
「Vue实践」项目升级vue-cli3的正确姿势
-
为何你始终理解不了JavaScript作用域链?
:heart: 看完三件事
如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:
-
点个 「在看」 ,让更多的人也能看到这篇内容( 喜欢不点在看,都是耍流氓 -_- )
-
关注我的 GitHub:github.com/yygmind ,让我们成为长期关系
-
关注公众号「高级前端进阶」, 每周重点攻克一个前端面试重难点 ,公众号后台回复「面试题」 送你高级前端面试题。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Base64 编码/解码
Base64 编码/解码
SHA 加密
SHA 加密工具