【三十天精通Vue 3】第二十六天 Vue3 与 TypeScript 最佳实践

✅创作者:陈书予
🎉个人主页:陈书予的个人主页
🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区
🌟专栏地址: 三十天精通 Vue 3
文章目录
- 引言
- 一、为什么使用TypeScript?
- 二、Vue 3和TypeScript的基础
- 2.1 安装TypeScript
- 2.2 配置TypeScript
- 2.3 Vue 3中使用TypeScript
- 三、Vue 3和TypeScript的进阶
- 3.1 类型检查
- 3.2 接口
- 3.3 枚举
- 3.4 泛型
- 3.5 装饰器
- 3.6 Mixins
- 四、Vue 3和TypeScript的最佳实践
- 4.1 单文件组件
- 4.2 组件通信
- 4.3 组件 Props
- 4.4 事件处理
- 4.5 生命周期
- 4.6 Vuex和TypeScript
- 4.7 Axios和TypeScript
引言
Vue.js 3.x是一种流行的JavaScript框架,它允许我们使用模板语法来快速开发应用程序、组件化和封装,同时还提供了高效的响应式数据绑定、组件通信等众多特性。相对于其前身Vue.js 2.x,Vue 3.x进一步增强了TypeScript的支持,使我们可以更容易地将TypeScript与Vue.js结合使用,以提高我们的代码质量、可维护性和开发效率。
本篇文章将从为什么使用TypeScript、TypeScript的优势、Vue 3和TypeScript的基础、Vue 3和TypeScript的进阶、以及Vue 3和TypeScript的最佳实践等几个方面介绍如何使用Vue 3和TypeScript进行开发。
一、为什么使用TypeScript?
TypeScript相比于JavaScript,有如下的优点:
1.静态类型检查:使用静态类型检查可以帮助我们在编码时发现一些隐藏的类型错误,从而在开发周期的早期就能够进行修改,避免在其他环节引入更严重的bug。
2.代码提示:使用TypeScript,开发者在写代码的时候会得到更全面、更准确的代码提示,这对开发效率和代码编写的准确性都有积极的影响。
3.代码可读性提高:使用TypeScript可以明确地表达代码中的数据类型、接口和方法的类型等信息,这能够提高代码的可读性。
4.文档自动生成:TypeScript可以根据代码生成文档,更加方便地为其他的开发者提供使用帮助。
5.维护成本降低:代码中的类型和接口可以帮助开发团队理解整个代码库,降低了维护代码的成本。
二、Vue 3和TypeScript的基础
在开始使用Vue.js 3和TypeScript编写代码之前,需要先安装TypeScript,配置TypeScript环境。
2.1 安装TypeScript
TypeScript的安装比较简单,可以使用npm工具进行安装。执行以下命令即可完成TypeScript的安装:
npm install -g typescript
2.2 配置TypeScript
在安装了TypeScript之后,我们需要进行一些简单的TypeScript配置,以便在开发Vue 3应用程序时使用。
TypeScript的配置文件为tsconfig.json,我们需要在Vue 3项目的根目录下添加一个tsconfig.json文件。例如,在默认的Vue 3项目文件夹中,该文件的路径为./tsconfig.json。我们可以通过以下的命令来创建tsconfig.json文件:
tsc --init
这个命令将生成一个包含默认设置的tsconfig.json文件。我们可以针对具体的项目,根据需要进行一些简单的编辑,比如指定目标JavaScript版本、配置编译选项等等。
2.3 Vue 3中使用TypeScript
默认情况下,Vue 3项目使用单文件组件(SFC)来管理其组件,而这些组件可以通过业务逻辑脚本文件中的JavaScript代码来实现。如果我们要使用TypeScript编写业务逻辑,就需要将.js文件转换为.ts文件。
我们可以在.vue文件中使用TypeScript,只需要在<script>标记中添加lang="ts"属性即可。下面是一个示例:
<template><div>{{ message }}</div>
</template><script lang="ts">
import { defineComponent } from 'vue';export default defineComponent({name: 'HelloWorld',props: {message: String},setup(props) {return {message: props.message};}
});
</script>
在这个例子中,我们可以看到<script>标记中的lang属性设置为"ts",这是告诉Vue 3,SFC文件中的脚本代码使用TypeScript编写。
三、Vue 3和TypeScript的进阶
3.1 类型检查
TypeScript最重要的一个特性就是类型检查,它可以帮助我们在代码编写过程中避免许多潜在的类型错误。在Vue 3中,我们也可以使用类型检查来增加代码的可维护性和健壮性。
下面是一个使用类型检查的示例:
import { defineComponent, PropType } from 'vue';interface User {name: string;age: number;address: string;
}export default defineComponent({name: 'UserCard',props: {user: {type: Object as PropType<User>,required: true}},setup(props) {const { user } = props;const isValid = (data: User): boolean => {return (data && data.name && data.age && data.address);};return {user: isValid(user) ? user : null};}
});
在这个示例中,我们使用了一个名为User的接口表示一个User对象,该对象包含name、age和address三个属性。由于props中的user是一个Object类型的值,我们需要使用PropType将其类型限定为User。
在setup()函数中,我们定义了一个名为isValid()的函数,用于检查传入的user对象是否合法,如果合法则返回该对象,否则返回null。这个函数会在组件的user属性被初始化时被调用,在组件的其它位置,也可以使用isValid()函数对任意User对象进行检查。
3.2 接口
TypeScript中的接口可以用来描述一个对象的形状(也就是属性、方法的集合),从而可以在多个地方进行类型检查。Vue 3中组件的props和emit选项可以使用接口来描述其类型。
下面是一个示例:
import { defineComponent } from 'vue';interface Props {message: string;
}interface Emit {change: (value: string) => void;
}export default defineComponent({name: 'HelloWorld',props: {message: {type: String,required: true}},emits: ['change'],setup(props, { emit }) {const handleChange = (event: Event) => {const value = event.target.value;emit('change', value);};return {handleChange};}
});
在这个示例中,我们定义了一个名为Props的接口,用于描述HelloWorld组件的props对象的形状,该对象包括一个名为message的字符串属性。
我们还定义了一个名为Emit的接口,用于描述HelloWorld组件的emit对象的形状,该对象包括一个名为change的事件。
在组件中,我们使用了Props接口来描述组件中的message属性,使用了Emit接口来描述组件的emit对象。我们还在组件中定义了一个名为handleChange()的函数,用于将输入框中的值传递给父组件,该函数会在输入框的值发生变化时被调用,并触发change事件。
3.3 枚举
TypeScript中的枚举可以方便地为一组相关的常量赋予一组有意义的名字,从而增加代码的可读性。Vue 3中也可以使用枚举来描述一些基于数字或字符串的常量。
下面是一个枚举的示例:
import { defineComponent } from 'vue';enum OrderStatus {Unpaid = 'unpaid',Paid = 'paid',Shipped = 'shipped',Delivered = 'delivered'
}export default defineComponent({name: 'OrderList',setup() {const orderStatusToString = (status: OrderStatus) => {switch (status) {case OrderStatus.Unpaid:return '待付款';case OrderStatus.Paid:return '已付款';case OrderStatus.Shipped:return '已发货';case OrderStatus.Delivered:return '已签收';}};return {orderStatusToString};}
});
在这个示例中,我们定义了一个名为OrderStatus的枚举,用于描述订单状态的四个值。我们还定义了一个名为orderStatusToString()的函数,用于将枚举值转换为相应的中文订单状态名称。
在组件的setup()函数中,我们通过return语句将orderStatusToString()函数暴露给模板。
3.4 泛型
TypeScript中的泛型可以方便地为函数或类中的类型参数添加类型约束,从而提供更加灵活和安全的泛型编程能力。Vue 3中的组件props和emit属性也可以使用泛型来描述其类型。
下面是一个示例:
import { defineComponent, PropType } from 'vue';interface User<T> {id: number;name: string;age: number;data: T;
}export default defineComponent({name: 'UserCard',props: {user: {type: Object as PropType<User<string>>,required: true}},setup(props) {const { user } = props;return {userName: user.name,userData: user.data};}
});
在这个示例中,我们定义了一个名为User的泛型接口,其中类型参数T表示data属性的类型。
在组件的props中,我们使用了PropType来将user属性限定为一个泛型类型为string的User对象。
在setup()函数中,我们从user属性对象中取出了它的name和data属性,并将它们暴露给模板。
3.5 装饰器
TypeScript中的装饰器是一种特殊的语法,可以用来修饰类、方法、属性和参数等,从而添加额外功能和约束。Vue 3支持使用装饰器来修饰组件、属性和方法等。常用的装饰器包括@Component、@Prop、@Emit、@Watch等。
下面是一个示例:
import { defineComponent } from 'vue';@Component
export default class HelloWorld extends Vue {@Prop({ type: String, required: true })message!: string;@Emit()handleClick() {console.log('click');}@Watch('message')handleWatch(newVal: string, oldVal: string) {console.log(`message has been changed from ${oldVal} to ${newVal}`);}
};
在这个示例中,我们使用了三个常用的装饰器:
@Component:用于修饰Vue 3组件类,将类声明为一个Vue组件。@Prop:用于修饰类中的属性,将属性声明为Vue组件的prop属性。@Emit:用于修饰类中的方法,将方法标记为发射的自定义事件。@Watch:用于修饰类中的方法,将方法标记为监视的数据变化。
3.6 Mixins
Mixins是一种复用组件逻辑的方式,Vue 3中的Mixins与TypeScript结合使用时需要注意,因为Mixins扩展的属性和方法类型不能添加到子类原有的类型定义中。为了解决这个问题,可以使用交叉类型或者泛型约束。
下面是一个示例:
import { defineComponent } from 'vue';interface Mixin {message: string;showMessage(): void;
}const MyMixin = {data() {return {message: 'Hello Mixin!'};},methods: {showMessage() {console.log(this.message);}}
};export default defineComponent({name: 'HelloWorld',mixins: [MyMixin as Mixin],setup() {const handleClick = () => {this.showMessage();};return {handleClick};}
});
在这个示例中,我们定义了一个名为Mixin的接口,用于描述Vue 3 Mixin中的属性和方法。我们还定义了一个名为MyMixin的Mixins对象,该对象包含一个data对象和methods对象。
在组件中,我们通过将MyMixin对象强制转换为Mixin接口类型并传给mixins选项,使组件可以复用MyMixin中的属性和方法。
最后,我们定义了一个名为handleClick()的函数,该函数会调用showMessage()方法。
四、Vue 3和TypeScript的最佳实践
4.1 单文件组件
在Vue 3和TypeScript中使用单文件组件时,建议在.vue文件中使用
同时,需要注意的是,如果要让Vue 3识别TypeScript文件,需要在项目中安装vue-tsc并且在tsconfig.json中正确配置:
{"compilerOptions": {..."module": "esnext","target": "esnext","jsx": "preserve","sourceMap": true,"strict": true,"esModuleInterop": true,"moduleResolution": "node","types": ["webpack-env","@types/node","@vue/cli-plugin-typescript"],"allowSyntheticDefaultImports": true,"resolveJsonModule": true,"isolatedModules": true,"noImplicitAny": false},"include": ["src/**/*.ts","src/**/*.tsx","src/**/*.vue"],"exclude": ["node_modules"]
}
4.2 组件通信
在Vue 3和TypeScript中,组件之间的通信可以使用props和event进行。
props可以定义组件之间所需的属性,并且可以在组件内部进行类型检查。例如:
interface Props {message: string
}export default defineComponent<Props>({props: {message: {type: String,required: true,},},...
})
event可以定义组件之间所需的事件类型,并且可以在组件内部进行类型检查。例如:
interface CustomEvents {click: () => void;
}export default defineComponent<{}, CustomEvents>({emits: ["click"],...
})
4.3 组件 Props
在Vue 3和TypeScript中,组件的props可以在组件内部进行类型检查,这可以更好地保证组件的健壮性。
例如,在组件定义时,可以使用Props interface定义prop的类型,并在props选项中进行声明。如下所示:
interface Props {message: string
}export default defineComponent<{}, {}, Props>({props: {message: {type: String,required: true,},},...
})
4.4 事件处理
在Vue 3和TypeScript中,事件处理的方式与JavaScript中相同,不需要进行特殊处理。不过为了确保正确性和代码的健壮性,建议定义事件的类型,并在组件的emits选项中进行声明。
例如:
interface CustomEvents {click: () => void;
}export default defineComponent<{}, CustomEvents>({emits: ["click"],...
})
4.5 生命周期
在Vue 3和TypeScript中,生命周期钩子仍然有效,但是需要在组件类型定义时,将使用到的生命周期钩子也进行声明。
例如:
export default defineComponent<{}, {}, {}, {}, {mounted: () => void;updated: () => void;
}>({mounted() {console.log("Mounted!");},updated() {console.log("Updated!");},...
})
4.6 Vuex和TypeScript
在使用Vuex和TypeScript时,需要定义store中的state、mutations和actions等类型,并在组件中使用mapState、mapMutations和mapActions等工具来连接store。
例如,定义store中的state类型:
interface State {count: number
}const store = createStore<State>({state: {count: 0,},...
})
在组件中使用mapState连接store:
import { mapState } from "vuex";
import { State } from "@/store";export default defineComponent({computed: {...mapState<State, "count">(["count"]),},...
})
4.7 Axios和TypeScript
在Vue 3和TypeScript中使用axios,需要安装axios和@types/axios库,并在组件中定义返回类型,并在代码中使用async/await或者Promise等方式来处理异步操作。
例如,在组件中定义一个API请求方法:
import axios, { AxiosResponse } from "axios";interface ResponseData {data: string;
}async function fetchData(): Promise<AxiosResponse<ResponseData>> {return await axios.get("/api/data");
}
在组件中使用async/await调用API请求:
export default defineComponent({async mounted() {const response = await fetchData();console.log(response.data);},...
})

相关文章:
【三十天精通Vue 3】第二十六天 Vue3 与 TypeScript 最佳实践
✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、为什么使用TypeScript?二、Vue 3和TypeScript…...
ffmpeg-mov-metadate不识别Bug修复
文章目录 BUG起因类似问题反馈问题解决具体步骤: 阅读过文章ffmpeg命令行解析调试流程记录movenc.c源码分析 BUG起因 在ffmpeg参数默认可识别的metadata参数如下: 具体可见libavformat/movenc.c->mov_write_udta_tag() mov_write_string_metadata(s,…...
(8)(8.6) 引导程序更新
文章目录 前言 1 我在哪里可以下载最新的引导程序? 2 使用任务规划器进行升级...
汽车电路图、原理框图、线束图、元器件布置图的识读技巧与要点
摘要: 想要读懂汽车电路图就必须把电的通路理清楚,即某条线是什么信号,该信号是输入信号、输出信号还是控制信号以及信号起什么作用,在什么条件下有信号,从哪里来,到哪里去。 一、汽车电路图的识读技巧 1.…...
( 数组和矩阵) 667. 优美的排列 II ——【Leetcode每日一题】
❓667. 优美的排列 II 难度:中等 给你两个整数 n 和 k ,请你构造一个答案列表 answer ,该列表应当包含从 1 到 n 的 n 个不同正整数,并同时满足下述条件: 假设该列表是 answer [a1, a2, a3, ... , an] ࿰…...
【python基础语法七】python内置函数和内置模块
内置全局函数 abs 绝对值函数 print(abs(-1)) # 1 print(abs(100)) # 100round 四舍五入 """奇进偶不进(n.5的情况特定发生)""" res round(3.87) # 4 res round(4.51) # 5 # res round(2.5) # 2 # res round(3.5) # 4 res round(6.5) # …...
81. read readline readlines 读取文件的三种方法
81. read readline readlines 读取文件的三种方法 文章目录 81. read readline readlines 读取文件的三种方法1. 读取文件的三种方法2. read方法3. readline方法4. readlines方法5. 代码总结5.1 read方法读取全部内容5.2 readline方法读取一行,返回字符串5.3 readli…...
【社区图书馆】【图书活动第四期】
目录 一、前言 二、作者简介 三、《PyTorch高级机器学习实战》内容简介 四、书目录 一、前言 今天,偶尔逛到csdn社区图书馆,看到有活动 “【图书活动第四期】来一起写书评领实体奖牌红包电子勋章吧!”(活动到今天结束…...
webpack学习指南(上)
构建流程 Webpack 的构建流程可以分为以下几个步骤: 解析配置文件:Webpack 会读取项目中的 webpack.config.js 文件,并解析其中的配置项。 解析入口文件:Webpack 通过配置文件中设置的 entry 入口,递归地解析出所有依…...
刷题记录˃ʍ˂
一、1033. 移动石子直到连续 思路 这道题是一道数学题,它一共分为三种可能 第一种可能为三个石子本来就是连续的时候 第二种可能为最少步数为1的时候,相邻石子不能大于一格 第三种可能为最少步数为2的时候,这时相邻石子大于一格 那么第二…...
Word2vec原理+实战学习笔记(二)
来源:投稿 作者:阿克西 编辑:学姐 前篇:Word2vec原理实战学习笔记(一) 视频链接:https://ai.deepshare.net/detail/p_5ee62f90022ee_zFpnlHXA/6 5 对比模型(论文Model Architectur…...
什么是Java的多线程?
Java的多线程是指在同一时间内,一个程序中同时运行多个线程。每个线程都是一个独立的执行路径,可以独立地执行代码。Java中的多线程机制使得程序可以更高效地利用计算机的多核处理器和CPU时间,从而提高程序的性能和响应能力。 创建和使用Jav…...
“use strict“是什么? 使用它有什么优缺点?
严格模式 - JavaScript | MDN Javascript 严格模式详解 - 阮一峰的网络日志 1、"use strict" 是什么? "use strict" :指定代码在严格条件下执行; 2、 使用 "use strict" 有什么优缺点? ① 严格模式通过抛出错…...
【C++】C++11常用特性总结
哥们哥们,把书读烂,困在爱里是笨蛋! 文章目录 一、统一的列表初始化1.统一的{}初始化2.std::initializer_list类型的初始化 二、简化声明的关键字1.decltype2.auto && nullptr 三、STL中的一些变化1.新增容器:array &…...
泛型——List 优于数组
数组与泛型有很大的不同: 1. 数组是协变的(covariant) 意思是:如果Sub是Super的子类型,则数组类型Sub[] 是数组类型Super[] 的子类型。 2. 泛型是不变的(invariant) 对于任何两种不同的类型Ty…...
JavaScript中对象的定义、引用和复制
JavaScript是一种广泛使用的脚本语言,其设计理念是面向对象的范式。在JavaScript中,对象就是一系列属性的集合,每个属性包含一个名称和一个值。属性的值可以是基本数据类型、对象类型或函数类型,这些类型的值相互之间有着不同的特…...
JavaScript通过函数异常处理来输入圆的半径,输出圆的面积的代码
以下为实现通过函数异常处理来输入圆的半径,输出圆的面积的代码和运行截图 目录 前言 一、通过函数异常处理来输入圆的半径,输出圆的面积 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 前言 1.若有选择,您可以…...
Ubuntu 安装 Mysql
主要内容 本文主要是实现在虚拟机 Ubuntu 18.04 成功安装 MySQL 5.7,并实现远程访问功能,以 windows 下客户端访问虚拟机上的 mysql 数据库。 1. 切换至 root 用户 ,shell 终端指令均执行在 root 用户下 sudo su 2. 安装并设置 mysql 安…...
【五一创作】【Midjourney】Midjourney 连续性人物创作 ② ( 获取大图和 Seed 随机种子 | 通过 seed 随机种子生成类似图像 )
文章目录 一、获取大图和 Seed 随机种子二、通过 seed 种子生成类似图像 一、获取大图和 Seed 随机种子 注意 : 一定是使用 U 按钮 , 在生成的大图的基础上 , 添加 信封 表情 , 才能获取该大图的 Seed 种子编码 ; 在上一篇博客生成图像的基础上 , 点击 U3 获取第三张图的大图 ;…...
分布式事务 --- Seata事务模式、高可用
一、事务模式 1.1、XA模式 XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
