在浏览网上的JavaScript相关文档时,大家可能已经注意到了一个趋势:越来越多的项目和教程都采用了TypeScript编写代码。对于那些没有TypeScript经验的人来说,阅读这些由TypeScript编写的代码可能会感到有些压力。
Vue3的出现无疑加剧了这种趋势。Vue3本身就是用TypeScript编写的,因此我们可以直接在Vue3中使用TypeScript,无需进行任何特殊设置。在实际的大型项目开发中使用TypeScript编写的情况会越来越普遍。为了帮助您更好地理解和阅读使用TypeScript编写的Vue代码,本文档将通过一些简单的示例来解释如何在Vue3中使用TypeScript。值得注意的是,TypeScript的主要功能是进行类型检查,所以在阅读代码时,请特别关注类型。
第一章 Vue3项目创建 1 Vue CLI 创建vue项目
第一章 Vue3项目创建 2 使用 Webpack 5 搭建 vue项目
第一章 Vue3项目创建 3 Vite 创建 vue项目
第二章 Vue3 基础语法指令
第三章 Vue Router路由器的使用
第四章 VUE常用 UI 库 1 ( element-plus,Ant ,naiveui,ArcoDesign)
第四章 VUE常用 UI 库 2 ( ailwind 后台框架)
第五章 Vue 组件应用 1( Props )
第五章 Vue 组件应用 2 ( Emit )
第五章 Vue 组件应用 3( Slots )
第五章 Vue 组件应用 4 ( provide 和 inject )
第五章 Vue 组件应用 5 (Vue 插件)
第六章 Pinia,Vuex与axios,VueUse 1(Pinia)
第六章 Pinia,Vuex与axios,VueUse 2(Vuex)
第六章 Pinia,Vuex与axios,VueUse 3(VueUse)
第六章 Pinia,Vuex与axios,VueUse 4(axios)
第七章 TypeScript 上
第七章 TypeScript 中
第七章 TypeScript 下 创建Trello 任务管理器
环境搭建
在vue3中创建typescript项目现在非常简单,使用Vite 构建项目的,在项目创建时候选择typescript选项。创建出来的项目是就typescript项目。这也是现在比较主流的创建方法,官网推荐的方式。
$ npm init vite@latest zht-vite-vue
Need to install the following packages:
create-vite@latest
Ok to proceed? (y) y
? Select a framework: » - Use arrow-keys. Return to submit.
Vanilla
> Vue
React
Preact
Lit
Svelte
Others
Select a variant: » - Use arrow-keys. Return to submit.
JavaScript
> TypeScript
Customize with create-vue ↗
Nuxt ↗
Done. Now run:
cd zht-vite-vue
npm install
npm run dev
使用Vue CLI创建TypeScript项目的也是在创建的时候选择typescript选项,创建出来的项目自带typescript。这里就不做过多描述了。
安装@vue/cli-plugin-typescript
@vue/cli-plugin-typescript
内部预置了ts-loader的配置,无需单独配置解析。参考插件 https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/cli-plugin-typescript 插件配置说明。
npm install @vue/cli-plugin-typescript --save-dev
项目升级typescript
在开发中有很多时候是项目前期阶段使用的是 javascript模式开发,但是到后起需要升级使用typescript模式开发。这个时候就需要在vue项目中导入typescript编译模式,下面将介绍一下如何在vite项目中升级到typescript模式。
要在项目中安装vue-tsc,它是一个基于 Volar 的类型检查工具,Volar 是VSCode中 Vue 的扩展。tsc不能单独编译.vue 文件,但 vue- tsc是一个可以执行类型检查的工具,包括内部模板
1 安装vue-tsc
cmd进入到项目根目录中tsc -v
查看是否安装了typescript 版本。如果没有安装typescript 就执行下面的命令安装typescript到项目中来。
npm i typescript --save-dev
命令行运行tsc --init
生成tsconfig.json
文件。用户会出现下面的错误内容,因为家用电脑权限问题。需要在com命名界面中输入 set-executionpolicy remotesigned指令。
tsc : 无法加载文件 C:\Program Files\nodejs\node_global\tsc.ps1,因为在此系统上禁止运行脚本。有关详细
所在位置 行:1 字符: 1
- tsc --init
PS D:\vue\zht-ts> set-executionpolicy remotesigned
PS D:\vue\zht-ts> tsc -vVersion 4.5.5
vue-tsc
是对 TypeScript 自身命令行界面 tsc
的一个封装,它的工作方式基本和 tsc
一致。除了 TypeScript 文件,它还支持 Vue 的单文件组件。它是基于 Vite 的配置对开发服务器和打包器进行 TypeScript 文件执行语法转译,而不会执行任何类型检查,这保证了 Vite 开发服务器在使用 TypeScript 时也能始终保持飞快的速度。
npm i vue-tsc --save-dev
安装完成后在package.json文件中可以看到如下typescript配置信息内容。
"devDependencies": {
......
"typescript": "^4.9.4",
"vue-tsc": "^1.0.24"
}
1 tsconfig.json文件配置
对于以前从未使用过 TypeScript 的人来说,还需要在TypeScript 安装文件夹中创建了一个名为 tsconfig.json 的文件。这个 tsconfig.json 文件是TypeScript的配置文件,通过对这个文件中的属性修改,来配置TypeScript 的设置,tsconfig.json 文件项目使用 TypeScript 的必备文件。
在项目根目中创建tsconfig.json文件,将文章中的配置好的TypeScript 配置信息复制粘贴到目中的tsconfig.json文件中。
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,//严格加载
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
将tsconfig.json中属性strict: true 更改为 true,表示模式设置成编辑器和 vue -tsc加载严格模式。
2 tsconfig.node.json文件
vite项目中使用typescript开发,需要在根目录下创建一个tsconfig.node.json文件,文件内容如下。
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
3 vue 脚本中加 ts
项目中安装typescript完成后,在 vue文件中加入typescript语法编译标识,script setup标签中加入lang=“ts”,这个vue文件中就可以使用typescript语法进行开发了。
在这两个文件中,除了组件被脚本标签的 lang 属性和 defineComponent 函数包围之外,与普通的 JavaScript 代码没有区别,并且没有类型设置。lang 属性是必需的,设置值 ts 代表 typescript。
由于数据属性msg是一个字符串,所以类型是字符串,但是即使你不设置,类型也会被类型推断自动设置为字符串。类型推断由 TypeScript 自动完成。
如果想通过类型推断来检查类型,将光标移动到msg属性,可以通过编辑器的函数检查msg类型是否为string。
<script setup lang="ts">
const mes:string ="typescript 中的属性"
</script>
<template>
<h1>{{mes}}</h1>
</template>
在vite中不能使用require引入资源,因为这个require函数是webpack提供的一种加载能力,而我们项目中并没有使用到webpack作为项目的构建工具,所以无法使用require函数来引入资源。我们引入typesrcipt外部类的时候需要使用的是Vite导入函数from,来将typesrcipt外部类资源载入,vite关于这一部分的官方有说明选择用vite开发项目的可以上官网了解一下vite其他功能。
TypeScript 操作
在设置TypeScript时,我们需要进行一些检查操作,但基本上,我们所要做的就是定义类型并进行设置。如果我们正在处理的是函数,那么这些类型就会被设定为参数输入值的类型和返回值类型。如果你尝试输入一个与已设定类型不匹配的值,或者编写了返回不同类型的代码,你将会收到一条错误消息。
换句话说,TypeScript使我们能够在编写代码的过程中发现错误,而不是等到运行时才发现。这样可以大大减少在生产环境中遇到错误的可能性。简而言之,使用TypeScript可以帮助我们提前发现和修正错误,从而提高代码的稳定性和可靠性。
1 设置属性类型
在 TypeScript 代码中,当你定义一个变量时需要设置这个变量的类型,变量要知道自己那种类型的值。常用的变量类型有一下几种String、Number、Array、Boolean、Function 和 Object,Void类型。下面我们将简单的介绍以上六种类型在Vue组件中的如何使用。
在 JavaScript 中脚本定义变量直接设置变量名称,在名称后边随便指定一个类型的值作为这个变量的值。在 JavaScript脚本中定义变量得时候没有明确变量的类型,因此可以现将变量设置成字符串,然后在设置成数值或者变成个函数等。
<script setup>
let name = "zht"
let age = 20;
let loading = true;
let score =“数字”;//设置成字符
score =3.123223;//重新赋值变为数字
//数组类型
let language = ['java','go','node','python'];
//函数类型
const info=()=>{
alert("info");
}
//对象类型
const userObject={name:"zht",dpetname:"部门",userid:12}
</script>
<template>
<h1>{{name}}</h1>
<h1>{{age}}</h1>
<h1>{{loading}}</h1>
<h1>{{score}}</h1>
<h1>{{language}}</h1>
</template>
1 基础属性设置
在TypeScript 与 JavaScript 代码最大的区别之一,在TypeScript 脚本中定义变量的时候一定要知道变得属性类型。TypeScript 定义变量的方法与面向对象语言一模一样,在它量名末尾添加 :(冒号)以指定类型。现在我们分别设置String、Number、Array、Boolean这几种类型的变量,为它们分别赋值。在TypeScript 中为变量赋值型 ,这个赋值类型一定要和属性的类型一致。
<script setup lang="ts">
let name:string = "zht"
let age:number = 20;
let loading:boolean = true;
let score:number =3.123223;
let language : array = ['java','go','node','python'];
</script>
<template>
<h1>{{name}}</h1>
<h1>{{age}}</h1>
<h1>{{loading}}</h1>
<h1>{{score}}</h1>
<h1>{{language}}</h1>
</template>
TypeScript 的属性类型一但被定义就不允许其他类型的值成为它的值了。如果出现下面的情况属性的值与属性的类型不一致编辑器就会报错。
<script setup lang="ts">
let name:string = "zht"
let score:number =3.123223;
name=1123.444;
score-"333";
</script>
<template>
<h1>{{name}}</h1>
<h1>{{score}}</h1>
</template>
属性是数组的情况下,要指定出来放入元素中值的类型。例如数组元素被定义成字符串数组这个数组中所有值得类型都应该是字符串。第二种定义数组的方法是使用泛型,来定义数组中的类型。使用关键字Array 定义属性为数组,在后边 < >号中来定义这个数组的类型。数组的定义描述如下。
- 属性类型[]
- Array<泛型>
let language : string[] = ['java','go','node','python'];
let language : Array<string> = ['java','go','node','python'];//泛型定义
//TypeScript 中的数组加上数据类型
let isarray: boolean[] = [true,false,false];
let isarray: Array<boolean> = [true,false,false];
2 函数对象
在Javascript脚本中定义函数类型的时候,是不检查如何参数和返回值类型的。例如创建一个函数 add ,设置这个函数有两个参数,返回结果是这两个参数相加的和。
function add(a,b){
return a + b;
}。
如果在 TypeScript 中定义这个函数,需要在其中的两个地方来指定数据类型,第一地方是函数的参数,第二地方是函数的返回值部分。在add 函数()括号中定义参数类型,定义过程和定义普通属性一样参数名后边号 :(冒号)跟一个属性类型,返回值在函数()括号后边加:(冒号)加返回值属性类型,如果没有返回值设置成void关键字。
<script setup lang="ts">
// add():void{} 无返回值得设置
function add(a: number,b: number): number{
return a + b;
}
alert(add(1,2));
</script>
<template>
</template>
上面是定义函数的方式,下面我们定义一个函数参数的定义方式。它的定义方法与上面讲到的直接定义函数方式不同。将函数名称设置成const的属性再函数名称后边 :(冒号)设置参数类型,(a: number, b: number) => number类型是函数返回值得类型。
<script setup lang="ts">
const add: (a: number, b: number) => number = (
a: number,
b: number
): number => {
return a + b;
};
alert(add(1,2));
</script>
<template>
</template>
为了方便操作与阅读代码一般会使用如下的方法好创建函数对象。
const sendMessages=(meg:string):string=>{
return meg;
}
3 对象设置
在Javascript脚本中创建对象属性类型,在这个对象中直属性名称加属性值的方法来定义对象中的值。不用为要设置的对象中的属性指定它对应的属性类型。
<script setup>
//对象类型
const userObject={name:"zht",dpetname:"部门",userid:12}
</script>
<template>
<h1>{{userObject.name}}</h1>
<h1>{{userObject.userid}}</h1>
<h1>{{userObject.deptname}}</h1>
</template>
在 TypeScript 中直接创建对象属性的时候与Javascript中相反,需要先设置对象中属性的类型,在设置属性类型的时候每个属性的分割符是“,”(逗号)而不使用“,”(逗号),不需要分号来为每个属性/类型对换行。然后在设置对象属性中的属性值,属性值类型必须和对象中定义的属性类一致。
<script setup lang="ts">
const user: { id: number; name: string ,dpetname:string} = {
id: 100,
name: 'zht',
dpetname:'部门一'
};
</script>
<template>
<h1>{{user.name}}</h1>
<h1>{{user.id}}</h1>
<h1>{{user.dpetname}}</h1>
</template>
2 方法与类型推断,类型断言
1 方法
上面我们简单的介绍了一下在 TypeScript 如何定义基本类型,现在我们在讲讲如何在给computed设置类型,这是Vue中特有的功能。方法定义与computed一样,需要设置方法返回值的类型。如果该方法有参数,也要设置参数的类型。如果没有设置返回值和参数的类型,TypeScript需要通过类型推断自动设置的它们的类型。因此即使没有设置方法的反回值与参数的类型也不会显示错误消息。
在App.vue文件中我们添加一个getSum函数来进行数值的累加功能,在普通的Vue组件中定义这个函数。
<script setup >
let count=0;
const getSum=()=>{
return count++;
}
</script>
<template>
</template>
现在让我们在TypeScript 模式中创建这个函数。在getSum方法的函数体后边通过设置 :(冒号)来确定返回值类型。如下所示:
<script setup lang="ts">
let count=0;
const getSum=():number=>{
return count++;
}
</script>
<template>
</template>
这样设置后如果getSum方法返回一个字符串,编辑器的后台会显示一条消息,这样开发者就会注意到代码中的错误。我们在修改getSum方法将它的参数都设置上类型,设置方法与TypeScript 中设置函数对象一样,在函数参数后边定义参数类型。
<script setup lang="ts">
let coun:number=0;
const getSum=(a1:number,b1:number):number=>{
return count=a1+b1;
}
</script>
<template>
</template>
2 类型推断
TypeScript 中会自动判断出没有定义类型的属性中的类型值,例如在脚本中定义一个msg属性没有设置它的类型值,但是编辑器中不会输出错误并且可以正常工作。这是因为当字符串被设置成msg 属性值得时候,TypeScript 会自动将属性的类型确定为字符串类型,这个过程就被称为类型推断。
但是属性类型一但被类型推断定义出来,就不可以在在赋值其他类型的值了。这里的msg属性被TypeScript 确定为字符串类型,如果在后面的代码中将它的值更改为数字,编辑器中出现错误信息提示。
<script setup lang="ts">
let msg="我是一个字符";//TypeScript 会推断类型为string
const onMsg=()=>{
msg=12222;//这个时候如果更改为数字,编辑器会出现错误
return msg;
}
</script>
<template>
{{onMsg()}}
</template>
上面的代码在编辑器中提示msg属性的类型错误,说明msg属性类型被推断为string类型。
3 类型断言
上面介绍了在 msg 属性中没有设置类型,TypeScrip会通过类型推断自动为他设置属性类型。TypeScrip中也有别外一种方式为没有设置类型的属性进行类型设置,就是使用 as 关键字来设置信息类型。这种使用 as 关键字设置类型的方法称为类型断言。
<script setup lang="ts">
let msg;
const onMsg=()=>{
return msg="我是一个字符" as string;//msg 属性类型被设置成字符串
}
</script>
<template>
{{onMsg()}}
</template>
如果msg值是字符串类型,但是被断言是number类型,编辑器显示错误消息。
<script setup lang="ts">
let msg;
const onMsg=()=>{
return msg="我是一个字符" as number;//断言成数字
}
</script>
<template>
{{onMsg()}}
</template>
在开发的时候属性可能会是多种类型,例如msg属性类型可能是字符串,也可以能会是数字,这个时候我们需要将属性类型断言是多种类型,union模式(as 类型1| 类型2)来描述属性关系。当把类型断言成多种属性关系的时候,属性值也可以设置成对应类型的值。
<script setup lang="ts">
let msg;
const onMsg=()=>{
return msg="我是一个字符" as number|string;
}
</script>
<template>
{{onMsg()}}
</template>
代码中的msg属性使用 as number|string断言后, msg 的值是字符串还是数字,编译器都不会在提示错误了。
方法中的参数也可以设置成这样的联合类型。在onMsg函数中设置一个参数,这个参数它的类型为number和string,在调用这个onMsg函数的时候传入的值也可以是字符与数字类型。
<script setup lang="ts">
let msg;
const onMsg=(msg:number|string)=>{
return msg;
}
</script>
<template>
{{onMsg("我是字符串")}}
</template>
3 数据对象与类型别名
1 数据对象
如果我们需要定义一个对象属性,这个对象中包含多种属性类型的参数,我们需要使用接口或者类类型来声明这个对象的类型。接口类型是更像是一种对象的类型约束,它并不包含参数值,只是定义参数的类型。我们可以通过接口看到对象由哪些属性和类型组成。
下面我们来定义一个对象属性,首先定义一个接口并声明这个接口的类型User类型,在User类型接口中设置name,dept,userid这三个属性,它们的属性类型为string 和 number。
interface User {
name: string;
dept: string;
userid: number;
}
我们使用了两种方法设置了这个接口的对象属性,第一种是as断言的方式,第二种事属性类型定义得方式。
<script setup lang="ts">
interface User {
name: string;
dept: string;
userid: number;
}
const user={name:'',dept:'',userid:1} as User;
const user1:User={name:'',dept:'',userid:1};
</script>
<template>
{{user}}
{{user1}}
</template>
</template>
在上面代码中接口的User类型已经设置给user对象,如果尝试将userid属性值改为字符串,会编辑器会报错。使用接口来规范对象属性中的属性值,这样和面向对象中对类的定义与使用可以一样。
<script setup lang="ts">
interface User {
name: string;
dept: string;
userid: number;
}
const user={name:'',dept:'',userid:1} as User;
const user1:User={name:'',dept:'',userid:1};
const onName=()=>{
user.userid="1222";//编辑器显示粗我信息
}
onName();
</script>
<template>
{{user}}
</template>
2 类型别名
类型别名用来给一个属性类型类起个新名字,在通过这个新名称来定义脚本中属性类型。type 是类型别名关键字,用这个关键字来命名别名名称。在 TypeScript 脚本中除了接口之外,还可以使用类型别名的方式来设置对象的属性类型。
在下面的例子中我们使用了type类型别名代替了interface定义User类中中的属性类型。代码中 type 为 接口对象设置类型。设置方式与interface类相同。在使用这个别名类型创建一个user对象,user对象的类型使用断言和定义的方法来指定。
<script setup lang="ts">
type User={
name: string;
dept: string;
userid: number;
}
const user={name:'',dept:'',userid:1} as User;
const user1:User={name:'',dept:'',userid:1} ;
</script>
<template>
{{user}}
</template>>
使用别名称定义属性与函数类型,通过别名的设置可以在代码中完成一些面向对象语言中的重载与覆盖。
<script setup lang="ts">
type Year = number;//别名定义属性类型
const myyear: Year = 2000;
type sumcount=()=>number;//别名定义函数类型
//创建别名执行函数
function onSum(sum:sumcount):number{
return sum();
}
onSum(function(){
return myyear;
});
onSum(()=>{
return myyear;
});
</script>
<template></template>