在Vue 中使用Typescript的示例代码

Vue 中使用 typescript

什么是typescript

typescript 为 javaScript的超集,这意味着它支持所有都JavaScript都语法。它很像JavaScript都强类型版本,除此之外,它还有一些扩展的语法,如interface/module等。

typescript 在编译期会去掉类型和特有语法,生成纯粹的JavaScript。

Typescript 5年内的热度随时间变化的趋势,整体呈现一个上升的趋势。也说明ts越来越️受大家的关注了。

安装typescript

npm install -g typescript
tsc greeter.ts

举个栗子

左右对比可以看出typescript 在编译期会去掉类型和特有语法,生成纯粹的JavaScript。

greeter.ts

interface Person {
 firstName: string;
 lastName: string;
}
function greeter(person: Person) {
 return "Hello, " + person.firstName + " " + person.lastName;
}
let user = { firstName: "Jane", lastName: "User" };
greeter.js
function greeter(person) {
 return "Hello, " + person.firstName + " " + person.lastName;
}
var user = { firstName: "Jane", lastName: "User" };

为什么需要使用它?

优势:

  1. 静态类型检查
  2. IDE 智能提示
  3. 代码重构
  4. 可读性

1. 静态类型检查

静态类型检查首要优点就是能尽早的发现逻辑错误,而不是上线之后才发现。

1.1 类型分析

传参过程字段错误,或类型错误使用。(进行参数标注后,在编码过程中即可检查出错误。)

1.2 类型推断:函数的返回值可通过ts类型推断得出.这一步骤是 在编译时进行

在编译时进行类型分析

example:

eg1: 我在使用ts写vue-router 的 动态路径参数时就发现了一个问题, 动态路径参数 以冒号开头 path: '/user/:id',我们会误认为id为一个number,如果使用ts你将得到提示 我们应该传入一个string类型的id. 传入一个number类型的id可能并不会出错,js会对它进行隐式类型转换,但是传入一个string会使它更安全和规范.

eg2: 个人使用后的效果

interface Person {
 firstName: string;
 lastName: string;
}
function greeter(person: Person): string {
 return "Hello, " + person.firstName + " " + person.lastName;
}
let user = { firstName: 1223, lastname: "User" };
greeter(user);

2.智能补全

在编写代码时ide就会提示函数签名.

interface Person {
 firstName: string;
 lastName: string;
}
/**
 * 问候语句
 * @param {Person} person
 * @returns {string}
 */
function greeter(person: Person): string {
 return "Hello, " + person.firstName + " " + person.lastName;
}
/**
 * hello word!
 *
 * @param {string} word
 * @returns {string}
 */
function Hello(word: string): string {
 return "hello," + word;
}
export { greeter, Hello };

直接将这个ts文件引入到其他ts文件中,不仅补全了所有的参数类型,还告诉你需要填入一个参数,并且你只有填入一个Person类型的对象才不会报错。(智能补全和参数校验)

3.在重构上

动态一时爽,重构火葬场.

typescript 在重构上的优势,我们主要从三方面说明。

1.重命名符号,可将一切引用的地方都进行修改。

在vs code 中如果我们想修改函数、变量或者类的名称,我们可以使用重命名符号的功能,在当前项目中正确的修改所有的引用.这个既可以在ts中使用,也可以在js中使用,而它的底层实现都是依靠ts 的语法分析器实现的。

2.自动更新引用路径(vs code)。

在重构的过程中,我们可能需要移动文件的路径,这往往会导致其他地方的import失效,这时候vs code提供了自动更新引用路径的功能。它的底层实现也是依靠ts 的语法分析器实现的。

3.校验函数签名。

有时候我们会重构类或函数的签名,如果有引用到的地方忘记修改,除了运行时候能发现,其他时候往往难以察觉,且 ESLint 也只能是排查简单的问题,所以出了BUG会非常麻烦。 而 TypeScript 不一样,在编码时就能及时的发现哪里错了,哪里应该改动但没有修改。

[函数签名 MDN][5]

4. 可读性

可读性上,TypeScript 明显占优,查看开源代码时,如果注释不是很完善,往往会看的云里雾里,而 TypeScript 在同等条件下,至少有个类型,能让自己更容易明白代码的参数、返回值和意图。

TS+Vue初探

配置

在正式开发之前,我们需要了解一些基本的配置。

1.tsconfig.json 是 ts 项目的编译选项配置文件. 在 ts 项目中如果你不添加这份文件,ts 会使用默认的配置. 扫描二维码获取配置项目。

ts-loader:Webpack 的TypeScript 加载器,就是为了让 webpack 编译 .ts .tsx文件。
TSLint:.ts .tsx文件的代码风格检查工具。(作用类似于ESLint)
vue-shim.d.ts:由于 TypeScript 默认并不支持 *.vue 后缀的文件,所以在 vue 项目中引入的时候需要创建一个 vue-shim.d.ts 文件,放在项目根目录下,例如 src/vue-shim.d.ts。

在Vue里面写TS的方式

图中内容应写在script中的lang="ts" 。

上图:使用 Vue.extend的基础用法。

下图:基于类的Vue组件

通过对比我们发现,上面的编码方式更接近我们平时JS的写法,但是我们并不能感受到ts的类型检查和类型推断。

下面张图的写法更有助于我们得到ts的类型检查。这需要我们引入 vue-class-component ,虽然template中还是不能得到补全,但是script 中的内容得到了更好的补全。 下面我们了解一下vue-class-component的作用。

vue-class-component & vue-property-decorator

vue-class-component 强化 Vue 组件,使用装饰器语法使 Vue 组件更好的跟TS结合使用。

vue-property-decorator在 vue-class-component 的基础上增加了更多与 Vue 相关的装饰器,使Vue组件更好的跟TS结合使用。

这两者都是离不开装饰器的,(decorator)装饰器已在ES提案中。Decorator是装饰器模式的实践。装饰器模式呢,它是继承关系的一个替代方案。动态地给对象添加额外的职责。在不改变接口的前提下,增强类的性能。下面我们以 钢铁侠 为例讲解如何使用 ES7 的 decorator。

以钢铁侠为例,钢铁侠本质是一个人,只是“装饰”了很多武器方才变得那么 NB,不过再怎么装饰他还是一个人,它本质是没有被改变的。所以,装饰器没有改变其继承关系,但也同样能够为它添加很多厉害的技能。简单的说,装饰器是在不修改一个类的继承关系的前提下,为一个类修改或添加成员。

装饰器主要接收的三个参数:

target 要在其上定义属性的对象。

key 要定义或修改的属性的名称。

descriptor 将被定义或修改的属性描述符。

下面我们通过代码中我们为一个人添加了飞行的功能:

typescript VS JavaScript

了解了上面的基础知识,现在我将同一段代码分别使用js 和 ts来书写,现在我们来对比他们之间的差别。

1.Props (Properties)

使用js,我们有很多中方式来定义组件的 Props,但是大多都掺杂了 Vue 的私有特征,与 ES 格格不入,例如左边的代码,明明我们是把这个对象的 prop 属性定义成为了一个包含两个 string 元素的对象,但是我们却可以直接通过这个对象来访问 "name" 字段,这很明显是不符合 ES 语义的。
再来看看右边的 TS 选手,通过 Prop 装饰器把指定的字段标记为了 Prop,既保留了 ES 语法的语义,而且还能与 Vue 完美的配合,更棒的是,我们可以在编码的过程中享受 TS 对 Prop 字段的静态类型检查。

2.Method 和 data

再来看看 Method,JS 中定义 method 还是有我们上面提到的那个不符合 ES 语义的毛病。而在 TS 中,method 不需要额外的装饰器——实例方法就会自动成为 Vue 组件的 method。类似的还有 data ,使用 TS 的语法,实例字段即可自动成为 Vue 组件的 data。

3.Computed

在传统的使用 JS 编写的 Vue 代码中,如果要定义计算属性,我们需要在 computed 属性中定义相应的函数。而这在 ES 中其实早就已经有了对应语义的语法——getter,所以在使用了 vue-class-component 的 vue 组件中,我们可以直接使用 getter 来定义计算属性,不管是在语法上还是在语义上,相比普通的 JS 都略胜一筹
总结:我们使用vue-class-component让vue组件的定义更加符合ES语义,使得TS能够更好的进行语法分析,并基于此进行类型检查。

业务场景中使用TS + Vue

1. 在Vue项目中定义data和props

这样的写法,让我产生了两个疑惑。

1.1 为什么使用 的写法

@Prop(Number!:) propA!: number

而不是

@Prop(Number) propA: number

1.2 为什么Prop需要前后写两次类型?

自我自答环节:

答1.1:因为我们定一个Phone这个类,没有对phone、condition这些字段通过constructor进行初始化,所以需要在属性上使用 显式赋值断言来帮助类型系统识别类型,这样能够让属性会被间接地初始化。

答1.2:前面括号里面的类型标注是Vue提供的类型检查。冒号后面的是为TS提供的类型标注。

2. 编写一个函数

这里我们将使用到js的接口,它经常用于定义复杂的参数类型和返回值类型。

上面的例子,我们需要为opts这个参数定义类型,方便后面编码时的使用,这时我们就需要编写一个接口来对它进行类型定义。这个接口里面包括三个必须属性和一个可选属性。必须属性在对象初始化的时候必须赋值,但是有时候某个对象中的属性可以被忽略的,不一定会被需要。我们可以将它设置为可选项。

随着业务的发展,一些参数的字段会变的越来越多,越来越复杂。可能你想有没有什么一劳永逸的方法,让接口更加简单,甚至让它自动的适应业务的变化。于是我想出了这样的代码:

上面的代码: 定义了一个键为string,他的值为number或string类型的接口,并且该接口的所有字段都是可选的,你甚至可以传入一个空对象。所以我们可以使用上面的接口可以代替下面的接口,但是反之不行.

然而我们不应该去绕开这些检查,因为这样ts就不会为你检查使用接口的对象应该存在那些属性或者方法了。使用ts的意义就被大大减弱了。

3. 编写第三方依赖

在日常的开发过程中,我们经常会遇到将第三方依赖引入到 TS 项目中没有类型检查的问题,这往往是因为这些项目没有提供类型定义文件。这个时候,我们可以手动为这些第三方库编写类型定义文件,类型定义文件在编译后会被完全忽略,所以并不会对现有代码产生影响。以上面这个较为复杂的函数为例,它的作用是将传入的所有的参数的所有字段合并到一个新的对象中并返回,尽管他的功能比较简单,但是为它编写类型定义还是需要一些 TS 的技巧。

1. 外部模块声明: 首先我们需要创建一个拓展名为 .d.ts 的文件,并在其中声明一个模块,声明的模块名称需要跟我们在其他文件中引入的路径相同。

2. 类型参数——泛型:首先让我们考虑最简单的情况,当传入一个参数的时候,extend 函数应该返回与参数类型相同的对象,但是我们在编写函数的时候并不知道用户会传入何种类型的参数,所以我们可以定义一个类型参数 T1,这时,extend 就被称为泛型函数,T1 也被称做泛型参数。在上面的例子中,extend 函数接受一个类型为 T1 参数并返回一个类型为 T1 的值,T1 需要用户手动传入,还好 TS 足够聪明,在绝大多数情况下,TS 可以根据参数类型来自动推断类型参数,免去了我们输入类型参数的繁琐步骤。只接受一个参数的 extend 函数并没有很复杂,我们可以继续考虑一些更复杂的情况。

这次让我们定义一个接受三个参数的 extend 函数,同时它也接受三个泛型参数,而它返回值类型呢,则是 T1, T2, T3 的交叉类型。交叉类型让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性,相当于对这些类型的成员求并集。 例如, T1 & T2 & T3 这个类型的对象同时拥有了这三种类型的成员。在这里,交叉类型就满足了我们对 extend 函数返回值类型的要求。值得注意的是,实际的 extend 函数可以接受不定个数的参数,也就是说,我们为它编写的类型定义也需要同时兼容接受不定个数参数的情况,这就需要 TS 提供的函数重载功能。

3. 重载:在大多数静态类型编程语言中,编译器允许存在参数类型、个数不同的多个同名函数,这个特性被称为函数重载。TS 支持函数重载的特性,所以我们可以定义多个接受不同数量参数的 extend 方法,在用户调用时,TS 会自动的在这些同名函数中选择正确的重载定义。有了函数重载的帮助,我们可以在使用 extend 的大多数场景下享受到类型检查的好处,只有在参数个数超过4个的时候,TS 才无法推断出返回值类型。需要注意的是在 JS 中,运行时并不提供函数重载的能力,我们无法定义多个同名函数,即使他们接受的参数数量并不相同,为了实现函数重载的效果,开发人员需要手动在单个函数中对参数的类型、数量做出判断。

到这里我们的第三方声明就完成了,即使一个简单函数的第三方声明,我们也运用了很多ts的相关知识。

个人感受

前面我们讲解了,使用在vue中使用ts能带给我们的种种便利,现在就我个人感受而言,说一下美中不足的地方。

1.即使使用了ts,template 部分仍没有静态类型检查和IDE智能提示,但官方成员表示在以后的 Vue 单文件中会提供这项功能。

2.将  Vue 单文件组件引入 TS  文件中,无法正确的提示其文件位置。

3.Vue  周边工具,比如  Vuex,它对ts的支持薄弱,大量的功能难以直接迁移到ts中,并且没有好的官方支持的方案。

4.毫无疑问,使用 TS 进行开发,相比于 JS ,我们需要花费更多的时间和精力。

(0)

相关推荐

  • 在Vue组件中使用 TypeScript的方法

    注意:此文并不是把vue改为全部替换为ts,而是可以在原来的项目中植入ts文件,目前只是实践阶段,向ts转化过程中的过渡. ts有什么用? 类型检查.直接编译到原生js.引入新的语法糖 为什么用ts? TypeScript的设计目的应该是解决JavaScript的"痛点":弱类型和没有命名空间,导致很难模块化,不适合开发大型程序.另外它还提供了一些语法糖来帮助大家更方便地实践面向对象的编程. typescript不仅可以约束我们的编码习惯,还能起到注释的作用,当我们看到一函数后我们立马

  • 在 Typescript 中使用可被复用的 Vue Mixin功能

    转到用 Typescript 写 Vue 应用以后,经过一轮工具链和依赖的洗礼,总算蹒跚地能走起来了,不过有一个很常用的功能 mixin,似乎还没有官方的解决方案. 既想享受 mixin 的灵活和方便,又想收获 ts 的类型系统带来的安全保障和开发时使用 IntelliSense 的顺滑体验. vuejs 官方组织里有一个 'vue-class-component' 以及连带推荐的 'vue-property-decorator',都没有相应实现.翻了下前者的 issue,有一条挂了好些时间的待

  • 详解在Vue中使用TypeScript的一些思考(实践)

    Vue.extend or vue-class-component 使用 TypeScript 写 Vue 组件时,有两种推荐形式: Vue.extend():使用基础 Vue 构造器,创建一个"子类".此种写法与 Vue 单文件组件标准形式最为接近,唯一不同仅是组件选项需要被包裹在 Vue.extend() 中. vue-class-component:通常与 vue-property-decorator 一起使用,提供一系列装饰器,能让我们书写类风格的 Vue 组件. 两种形式输出

  • vue与TypeScript集成配置最简教程(推荐)

    前言 Vue的官方文档没有给出与TypeScript集成的具体步骤,网上其他的教程不是存在问题就是与vue-cli建立的项目存在差异,让人无从下手. 下面我就给出vue-cli建立的项目与TypeScript集成的最简配置. 初始化项目 首先用vue-cli建立webpack项目.这里为了演示方便,没有打开router和eslint等,可以根据自身情况打开. # vue init webpack vue-typescript ? Project name vue-typescript ? Pro

  • Vue2 Vue-cli中使用Typescript的配置详解

    前言 因为最近公司的团队热衷于vue框架,新项目想着练练typescript,于是开始了vue+ts的踩坑之路...本文意在为和我有一样想法的伙伴们省去踩坑的时间,下面话不多说了,来一起看看关于Vue2 Vue-cli中利用Typescript需要的配置是什么吧. 一.初步配置 首先安装官方插件vue-class-component,vue-property-decorator,配置webpack. webpack配置如下: 修改入口文件 entry: { app: './src/main.ts

  • 在Vue 中使用Typescript的示例代码

    Vue 中使用 typescript 什么是typescript typescript 为 javaScript的超集,这意味着它支持所有都JavaScript都语法.它很像JavaScript都强类型版本,除此之外,它还有一些扩展的语法,如interface/module等. typescript 在编译期会去掉类型和特有语法,生成纯粹的JavaScript. Typescript 5年内的热度随时间变化的趋势,整体呈现一个上升的趋势.也说明ts越来越️受大家的关注了. 安装typescrip

  • 如何在vue中使用ts的示例代码

    本文介绍了如何在vue中使用ts的示例代码,分享给大家,具体如下: 注意:此文并不是把vue改为全部替换为ts,而是可以在原来的项目中植入ts文件,目前只是实践阶段,向ts转化过程中的过渡. ts有什么用? 类型检查.直接编译到原生js.引入新的语法糖 为什么用ts? TypeScript的设计目的应该是解决JavaScript的"痛点":弱类型和没有命名空间,导致很难模块化,不适合开发大型程序.另外它还提供了一些语法糖来帮助大家更方便地实践面向对象的编程. typescript不仅可

  • 在Vue中使用antv的示例代码

    一,在vue原型中使用 1.首先安装antv/g2 yarn add @antv/g2 --save 2.在main.js中挂在到vue原型实例中 const G2 = require('@antv/g2') Vue.prototype.$G2 = G2 3.在vue文件中可以直接在mounted生命周期中直接使用 <template> <div> <div id="c1"></div> </div> </templat

  • Vue中key的作用示例代码详解

    Vue中key的作用 key的特殊attribute主要用在Vue的虚拟DOM算法,在新旧Nodes对比时辨识VNodes.如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改.复用相同类型元素的算法,而使用key时,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素.此外有相同父元素的子元素必须有独特的key,重复的key会造成渲染错误. 描述 首先是官方文档的描述,当Vue正在更新使用v-for渲染的元素列表时,它默认使用就地更新的策略,如果数据项的

  • vue中使用heatmapjs的示例代码(结合百度地图)

    业务需求:将heatmap引入页面中,做成一个可引入的框架,使用于所有页面.代码如下. <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> .heatmap { width:1900px; height:1900px; } </style> <script src="js/h

  • Vue中使用Sortable的示例代码

    之前开发一个后台管理系统,里面用到了Vue和Element-UI这个组件库,遇到一个挺有意思的问题,和大家分享一下. 场景是这样,在一个列表展示页上,我使用了Element-UI的表格组件,新的需求是在原表格的基础上支持拖拽排序.但是原有的组件本身不支持拖拽排序,而且由于是直接引入的Element-UI,不方便修改它的源码,所以比较可行的方法只能是直接操作DOM. 具体的做法是在mounted生命周期函数里,对this.$el进行真实DOM的操作,监听drag的一系列事件,在事件回调里移动DOM

  • vue中的适配px2rem示例代码

    前言 做移动端时,适配 是必须的.使用rem单位,可在不同屏幕上完美显示相同的布局.px2rem 插件方便的将px单位转为了rem. px2rem 地址:https://www.npmjs.com/package/px2rem 这应该是vue项目在适配移动端时候,最简单的方法之一 下面是基本步骤(使用cnpm) 1.下载并引入lib-flexible cnpm install --save lib-flexible 在main.js中 :import 'lib-flexible/flexible

  • Vue-cli3中使用TS语法示例代码

    目录 ts有什么用? 为什么用ts? 1.引入Typescript包 2.配置 3.让项目识别.ts 4.vue组件的编写 ts有什么用? 类型检查.直接编译到原生js.引入新的语法糖 为什么用ts? TypeScript的设计目的应该是解决JavaScript的“痛点”:弱类型和没有命名空间,导致很难模块化,不适合开发大型程序.另外它还提供了一些语法糖来帮助大家更方便地实践面向对象的编程. typescript不仅可以约束我们的编码习惯,还能起到注释的作用,当我们看到一函数后我们立马就能知道这

  • vue 运用mock数据的示例代码

    本文介绍了vue 运用mock数据的示例代码,分享给大家,具体如下: 初始化你的项目 话不用啰嗦,首先初始化你的项目,最简单的就是使用vue-cli啦 vue init webpack 引入mock.js 安装 mockjs npm install --save-dev mockjs 引入到Vue原型上,方便使用 import mockjs from 'mockjs' Vue.prototype.$mock = Vue.$mock = mockjs.mock 以上引入到Vue原型上,可以使用 t

  • Vue 中使用 typescript的方法详解

    什么是typescript typescript 为 javaScript的超集,这意味着它支持所有都JavaScript都语法.它很像JavaScript都强类型版本,除此之外,它还有一些扩展的语法,如interface/module等. typescript 在编译期会去掉类型和特有语法,生成纯粹的JavaScript. Typescript 5年内的热度随时间变化的趋势,整体呈现一个上升的趋势.也说明ts越来越️受大家的关注了. 安装typescript npm install -g ty

随机推荐