【三十天精通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 规范 提供了支持。…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...