完整的vite + ts + vue3项目,克隆就能用,傻瓜式保姆教程(第二篇)

目录

前言

一、基础知识准备

1.1 接口请求 (本篇重点内容)

1.1.1 Fetch API

1.1.2 XMLHttpRequest

1.1.3 axios(推荐)

1.1.4 EventSource

1.1.5 WebSocket

1.2 ts 类型定义 (本篇内容)

1.3 svg 雪碧图(本篇内容)

1.4  i18n 多语言(本篇内容)

1.5 公共工具方法(非本篇内容)

1.5.1 本地存储相关

a)cookie

b)localStorage

1.5.2 日期相关

a)格式化和计算

b)时差问题

1.5.3 设备区分

a) userAgent

b)h5 唤起 APP

1.5.4 判断 js 类型 (is)

1.5.5 上传文件

1.5.6 下载文件

a)浏览器能预览的文件

b)浏览器不能预览的文件

1.5.7 防抖和节流

1.6 部署

小结

二、增加接口请求模块

2.1 使用 axios 模块

2.1.1 安装 axios 模块

2.1.2 新建 service 文件夹

2.1.3 新建 request.ts

2.1.4 创建 axios 请求实例

2.1.5 提交代码

2.2 增加错误处理

2.2.1 新建 error.ts 

2.2.2 新建 handleError.ts

2.2.3 应用 handleError 方法

2.3  增加 web 请求方法

2.3.1 定义接口列表

2.3.2 封装 API 类

2.3.3 实例化 API 类

2.3.4 测试一下静态函数

2.3.5 测试一下非静态函数

2.4 优化请求模块

2.4.1 优化请求地址

三、ts 类型定义

3.1 新建 typings 文件夹

3.2 新建 index.d.ts

3.3 提交代码

四、增加 svg 雪碧图

4.1 配置插件

4.1.1 安装 vite-plugin-svg-icons

4.1.2 在 vite.config.ts 中配置

4.1.3 在 main.ts 中引入

 4.1.4 创建 src/images/svgs 文件夹

4.2 使用插件

4.2.1 新建 SvgIcon.vue

4.2.2 在 login.vue 中使用

4.2.3 运行效果

4.2.4 提交代码

五、i18n 多语言

5.1 安装和配置

5.1.1 安装 vue-i18n

5.1.2 新建 i18n 文件夹

5.1.3 更新 zh.ts & en.ts

5.1.4 更新 index.ts

5.1.5 在 main.ts 注册

5.2 使用多语言

5.2.1 在 login.vue 中使用

5.2.2 运行效果

5.3 提交代码

总结


前言

这篇文章是在之前的这篇小白教程的基础上进行的,建议先完成之前的文章的学习。请去我的gitee仓库拉取代码,代码相对于小白教程的文章有部分优化内容(下图),在教程中没有详细指出,可以参照提交记录学习。

一、基础知识准备

一个完整的 vue 工程化项目,除了这篇文章完成的基础建设之外,还有必不可少的几个模块,分别是:

1.1 接口请求 (本篇重点内容)

常见的接口请求方式有

1.1.1 Fetch API

Fetch API 是比较简单的原生接口请求方式,支持 Promise 但是兼容不太好,不推荐整个项目都使用。

1.1.2 XMLHttpRequest

XMLHttpRequest 是原生ajax 请求的方法,不支持 Promise,用起来需要自己封装,不推荐使用。

1.1.3 axios(推荐)

axios 是基于 XMLHttpRequest 封装的比较成熟的前端请求库,推荐使用。本篇文章主要介绍的是使用 axios 封装请求。 

1.1.4 EventSource

用来建立长链接,接收服务器推送的消息,可以参考这篇文章,请按需使用。

1.1.5 WebSocket

WebSocket 基于 tcp 协议,可以实现客户端和后端双向交换消息,请按需使用。

1.2 ts 类型定义 (本篇内容)

ts 项目都需要一个 typing.d.ts 进行类型定义

1.3 svg 雪碧图(本篇内容)

使用插件实现对 svg 图标的压缩和管理,vite 项目可以使用 vite-plugin-svg-icons

关于svg 图标相关知识,可以参考这篇文章。

1.4  i18n 多语言(本篇内容)

i18n 是一个成熟的国际化工具,用来实现页面上的语言切换

1.5 公共工具方法(非本篇内容)

1.5.1 本地存储相关

本地存储包括 cookie、localStorage、indexDB等

a)cookie

对于 cookie 过期时间的处理比较麻烦,建议不要自己写方法,已经有成熟的库 js-cookie 可供我们使用了。

b)localStorage

localStorage 存储数据涉及到对对象和数组的存储,为了使用方便,我们一般封装几个获取对象/数组的方法,将使用原生方法 localStorage.getItem 获取的值进行 JSON.parse 再返回对象/数组。

1.5.2 日期相关

a)格式化和计算

不要要在自己格式化和计算日期了,moment 插件帮你解决各种日期转换问题。

b)时差问题

用时间戳彻底解决前端的时差问题,其他的问题丢给后端,请参考这篇文章。

1.5.3 设备区分

a) userAgent

使用 navigator.userAgent 进行设备、浏览器的区分

b)h5 唤起 APP

使用 callapp-lib

1.5.4 判断 js 类型 (is)

可以使用is 库,也可以自己实现常用的方法,因为比较简单

1.5.5 上传文件

上传图片、文件

1.5.6 下载文件

a)浏览器能预览的文件

pdf、txt 等使用ajax

b)浏览器不能预览的文件

直接使用 window.location.href 即可

1.5.7 防抖和节流

使用 lodash

1.6 部署

使用 vercel 部署

小结

全部的内容非常多,所以本篇文章不包含5、6这两部分内容,对于其他内容也不具体解释每个模块的细致原理和功能,只详细介绍写代码的流程步骤。

再次强调,在开始之前,需要在仓库的的这个合并拉一个新的分支 feat-project

二、增加接口请求模块

流程图如下,建议克隆代码,一步一步的跟着来,本质是对 axios 的封装。

2.1 使用 axios 模块

2.1.1 安装 axios 模块

pnpm i axios

2.1.2 新建 service 文件夹

在 src 下新建 service 文件夹

2.1.3 新建 request.ts

在 service 文件夹下新建 request.ts

2.1.4 创建 axios 请求实例

(1)在 request.ts 中使用创建 axios请求实例

(2)源代码

import axios, { AxiosInstance } from 'axios'function createRequestInstance(url: string): AxiosInstance {const instance = axios.create({timeout: 1000 * 60 * 5, // 超时时间withCredentials: true, // 允许跨域携带cookiebaseURL: url, // 请求地址})return instance
}export default createRequestInstance

2.1.5 提交代码

2.2 增加错误处理

2.2.1 新建 error.ts 

(1)在 service 目录下增加 error.ts 文件,用于axios 请求的错误处理

(2) 在 error.ts 中增加 AxiosRequestError 类,将 axios 原生的错误类型(AxiosError)封装成我们自定义的错误类型,并对一些常见的错误码进行处理

(3)源代码

import { AxiosError } from 'axios'// 服务器报错返回 Error 的时候的数据结构,可以和后端商量定义,但是所有接口的格式要统一
export type ErrorResponse = {status: number // http 状态码,这个是必须的// 其他自定义类型类型
}class AxiosRequestError extends Error {data: ErrorResponse | undefinedraw: AxiosErrorisUnAuthorized = false // 权限错误 401isServerError = false // 服务器错误 500 等constructor(status: number, message: string, raw: AxiosError, data?: ErrorResponse) {// 调用父类「Error」的构造函数super(message)this.data = data // 后端返回的 datathis.raw = raw // axios 返回的原始数据this.isUnAuthorized = status === 401this.isServerError = status >= 500this.message = this.message || '' //给用户展示的错误消息,后续可以自定义}
}export default AxiosRequestError

(4)提交代码

2.2.2 新建 handleError.ts

(1)在 service 文件夹下增加 handleError.ts


(2)新增 handleError 方法

在 handleError.ts 中调用 AxiosRequestError 类,将 axios 默认的 AxiosError 转成我们处理过的  AxiosRequestError 类

(3) 源代码

import { AxiosError } from 'axios'
import AxiosRequestError, { ErrorResponse } from './error'// 把 axios 的 错误 转成 我们已经封装的 AxiosRequestError 类,统一处理
export function handleError(error: AxiosError | AxiosRequestError): AxiosRequestError {const err = error instanceof AxiosRequestError ? error : new AxiosRequestError(error.response?.status || 1, error.message, error, error.response?.data as ErrorResponse)return err
}

(4)提交代码

2.2.3 应用 handleError 方法

(1)在 request.ts 中应用handleError,增加 axios 响应的拦截器,对错误进行处理

(2) 源代码

import axios, { AxiosInstance } from 'axios'
import { handleError } from './handleError'function createRequestInstance(url: string): AxiosInstance {const instance = axios.create({timeout: 1000 * 60 * 5, // 超时时间withCredentials: true, // 允许跨域携带cookiebaseURL: url, // 请求地址})instance.interceptors.response.use(async res => {return res},async err => {err = await handleError(err)return Promise.reject(err)},)return instance
}export default createRequestInstance

(3)提交代码

2.3  增加 web 请求方法

2.3.1 定义接口列表

(1)在 service 下面增加 apiList.ts 存放系统中所有的请求地址

(2)在 apiList.ts 中随便定义接口

(3)源代码

// 系统中所有请求的接口
export const APIs = {login: '/login',// 还可以这样分成功能模块user: {Info: '/userinfo',},
}

 (4)提交代码

2.3.2 封装 API 类

(1)增加 requestList.ts

(3)封装 API 类

(3) 源代码

import { AxiosRequestConfig, AxiosResponse } from 'axios'
import createRequestInstance from './request'class API {request!: ReturnType<typeof createRequestInstance>get!: <T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig) => Promise<R>delete!: <T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig) => Promise<R>head!: <T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig) => Promise<R>options!: <T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig) => Promise<R>post!: <T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig) => Promise<R>put!: <T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig) => Promise<R>patch!: <T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig) => Promise<R>constructor(options: { url: string }) {const request = createRequestInstance(options.url)this.request = requestthis.post = request.post.bind(this)this.put = request.put.bind(this)this.get = request.get.bind(this)this.delete = request.delete.bind(this)this.head = request.head.bind(this)this.options = request.options.bind(this)this.patch = request.patch.bind(this)}
}export default API

(4)提交代码

2.3.3 实例化 API 类

(1) 增加 webRequest.ts

(2)实例化API类,增加 axio的拦截器

(3)源代码

import API from './requestList'
import AxiosRequestError from './error'
import { handleError } from './handleError'const $api = new API({url: 'https://xxx.com/api', // 这个是请求的后台的服务的地址
})// 请求的拦截器
$api.request.interceptors.request.use((config: any) => {const headers = config.headers || {}// 这个地方可以自定义请求头config.headers = {...headers,language: 'en', // 这个是自定义的请求头,还可以加 token 等}return config
})// 响应的拦截器
$api.request.interceptors.response.use(undefined, async (err: AxiosRequestError) => {err = handleError(err) // 调用我们自定义的 错误处理方法if (err.isUnAuthorized) {// 未授权的情况的处理}// 还可以自定义其他的情况的处理return Promise.reject(err)
})// 在 page 页面就可以直接调用这个 $api 请求接口
export default $api

(4)提交代码

2.3.4 测试一下静态函数

(1)增加API 类的静态函数

在 requestList.ts 中的 API 类中增加静态方法 getUserInfo 

(3)在 App.vue 中调用

(4)npm run dev 运行项目

(5)提交代码

2.3.5 测试一下非静态函数

(1)在 App.vue 测试

(2)效果

 (3)提交代码

2.4 优化请求模块

2.4.1 优化请求地址

实际项目中,我们需要区分请求的测试服务地址和正式服务地址,所以在 3.3 的步骤中,webRequest.ts 中 实例化 API 类的过程中 url的地址就不能写成一个固定的字符串。本节中我们对这一部分做优化。

(1)新建 env.ts

在 src 目录下新建 global 文件夹放通用配置文件,在 global 文件夹下面新建 env.ts 用于配置项目的环境变量(用于区分测试环境和正式环境)

(2)定义环境变量和获取环境变量的函数

(3)修改 request.ts

将 service/request.ts 中的函数参数变成一个函数,用于调用获取环境变量的函数

(4)修改 requestList.ts

修改在 API 类构造函数中调用 createRequestInstance 的参数

(5)修改 webRequest.ts 

修改实例化 API 类的地方的参数

(6)测试一下测试环境

运行 npm run dev 测试一下配置的地址是否正确

(7)测试一下正式环境

 (8)还原(7)中修改的 env.ts 中的代码

最终的env.ts的代码如下

// 正式环境
export const PROD_ENV = {SERVER_URL: 'https://xxx.com/api', // 服务地址IS_DEV: 'false', // 是否是测试环境
}// 测试环境
export const DEV_ENV = {SERVER_URL: 'https://xxx-test.com/api',IS_DEV: 'true',
}// 假设测试环境的域名是 https://xxx-test.com
const isDev = process.env.NODE_ENV === 'development' || ['xxx-test.com'].includes(location.host)export type EnvKey = keyof typeof PROD_ENV// 调用这个函数获取当前的环境变量
export function getProcessEnv(key: EnvKey): string | void {if (isDev) {if (DEV_ENV[key] !== undefined) {return DEV_ENV[key]}return ''}if (PROD_ENV[key] !== undefined) {return PROD_ENV[key]}
}

(9)提交代码

再确认一下,这个小节,主要的工作:

  1. 增加一个配置文件 env.ts
  2. 修改了一个函数的参数(request.ts 中的 createRequestInstance)导致了修改了三个文件

 

至此,本项目中的接口请求模块结束。

三、ts 类型定义

对于ts项目,可以自定义数据的类型,对于一些没有提供类型定义的第三方模块,我们为了解决编辑器报的ts类型错误,也可以自定义ts类型

3.1 新建 typings 文件夹

在src 目录下新建 typings文件夹,存放类型文件

3.2 新建 index.d.ts

在 typings 文件夹下面新建 index.d.ts 用于类型定义

3.3 提交代码

四、增加 svg 雪碧图

4.1 配置插件

4.1.1 安装 vite-plugin-svg-icons

pnpm i vite-plugin-svg-icons -D

4.1.2 在 vite.config.ts 中配置

4.1.3 在 main.ts 中引入

import 'virtual:svg-icons-register'

 4.1.4 创建 src/images/svgs 文件夹

随便弄个svg 图片放入 src/images/svgs 文件夹下,项目中的那个vue.svg 就是现成的

4.2 使用插件

4.2.1 新建 SvgIcon.vue

在 src/components 目录下新建 SvgIcon.vue

4.2.2 在 login.vue 中使用

4.2.3 运行效果

4.2.4 提交代码

五、i18n 多语言

5.1 安装和配置

5.1.1 安装 vue-i18n

pnpm i vue-i18n

5.1.2 新建 i18n 文件夹

在 src/global 下面新建 i18n 文件夹,同时在该文件夹下新建 index.ts 、en.ts、zh.ts

5.1.3 更新 zh.ts & en.ts

5.1.4 更新 index.ts

5.1.5 在 main.ts 注册

5.2 使用多语言

5.2.1 在 login.vue 中使用

5.2.2 运行效果

运行 npm run dev ,点击按钮可以切换语言

5.3 提交代码

总结

至此,本片文章内容结束,一个完整的vite 项目还剩两个部分,一个是公共函数一个是部署,这将在下一片文章完成。

其实到这里整个项目基本就完成了,剩下的公共函数可以等你用到的时候再写也来得及,至于部署的部分,每个公司的部署流程也不一样,也看你的需求了。

项目地址是,learn-vite: 搭建简单的vite+ts+vue框架

有问题欢迎在评论区指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/230600.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BearPi Std 板从入门到放弃 - 先天神魂篇(3)(RT-Thread I2C设备 读取光照强度BH1750)

简介 使用BearPi IOT Std开发板及其扩展板E53_SC1&#xff0c; SC1上有I2C1 的光照强度传感器BH1750 和 EEPROM AT24C02&#xff0c; 本次主要就是读取光照强度; 主板: 主芯片: STM32L431RCT6LED : PC13 \ 推挽输出\ 高电平点亮串口: Usart1I2C使用 : I2C1E53_SC1扩展板 : LE…

基于网络爬虫技术的网络新闻分析

目录 前言 一、网络爬虫技术 二、代理IP 三、网络新闻分析 总结&#xff1a; 前言 随着互联网的发展和普及&#xff0c;网络新闻成为人们获取信息的重要途径。然而&#xff0c;由于网络新闻的数量庞大&#xff0c;分析和处理这些新闻变得愈发困难。本文将介绍如何使用网络…

竞赛保研 python的搜索引擎系统设计与实现

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python的搜索引擎系统设计与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;5分创新点&#xff1a;3分 该项目较为新颖&#xff…

代码随想录算法训练营第55天| 392.判断子序列 115.不同的子序列

JAVA代码编写 392.判断子序列 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"…

Linux服务器性能优化小结

文章目录 生产环境监测常见专业名词扫盲服务器平均负载服务器平均负载的定义如何判断平均负载值以及好坏情况如果依据平均负载来判断服务器当前状况系统平均负载和CPU使用率的区别 CPU上下文切换基本概念3种上下文切换进程上下文切换线程上下文切换中断上下文切换 查看上下文切…

Java后端问题排查经验

线上出现问题首先应该做什么&#xff0c;不是解决问题&#xff0c;而是先恢复系统&#xff0c;把损失降到最小&#xff0c;有机会的话保留日志等数据用于后期问题复盘分析。解决问题可以后期慢慢复现排查&#xff0c;而线上用户的体验则不能多耽误一分一秒&#xff0c;任何线上…

word怎么分页?学会这几招,轻松掌握分页功能!

Microsoft Word作为办公文档处理的主力工具&#xff0c;其强大的排版功能为用户提供了丰富的文档编辑体验。其中&#xff0c;分页是一个常用但可能被忽视的重要功能&#xff0c;能够使文档结构更清晰、更易读。本文将向您介绍word怎么分页的三种方法&#xff0c;帮助您更好地掌…

Linux消息队列 msgget()、msgsend()、msgrcv()、msgctl()

一、消息队列 1、消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 2、每个数据块都被认为是有一个类型&#xff0c;接收者进程接收的数据块可以有不同的类型值 3、消息队列与管道不同的是&#xff0c;消息队列是基于消息的&#xff0c;而管道是基于字节流的&…

目标跟踪 MOT数据集和可视化

目录 MOT15数据集格式简介 gt可视化 本人修改的GT可视化代码&#xff1a; MOT15数据集格式简介 以下内容转自&#xff1a;【目标跟踪】MOT数据集GroundTruth可视化-腾讯云开发者社区-腾讯云 MOT15数据集下载&#xff1a;https://pan.baidu.com/s/1foGrBXvsanW8BI4eybqfWg?…

C语言学习第二十六天(算法的时间复杂度和空间复杂度)

1、算法效率 衡量一个算法的好坏&#xff0c;是从时间和空间两个方面来衡量的&#xff0c;换句话说就是从时间复杂度和空间复杂度来衡量的 这里需要补充一点&#xff1a;时间复杂度是衡量一个算法的运行快慢&#xff0c;空间复杂度是主要衡量一个算法运行所需要的额外空间。 …

【操作系统】实验五 文件系统

实验目的&#xff1a; 1. 掌握文件系统的基本概念和工作机制 2. 掌握文件系统的主要数据结构的实现 3、掌握软件系统实现算法 实验内容&#xff1a; 设计并实现一个虚拟的一级&#xff08;单用户&#xff09;文件系统程序 提供以下操作 1、文件创建/删除接口命令 2、目录创建/删…

Java基于微信小程序的小区车位租赁系统的设计与实现

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 简介技术路线需求分析用户信息管理车位信息管理车位申请管理论坛信息管理 效果图推荐阅读 简介 …

【强化学习-读书笔记】动态规划(策略评估、价值迭代、策略迭代算法)

参考 Reinforcement Learning, Second Edition An Introduction By Richard S. Sutton and Andrew G. Barto动态规划 (Dynamic Programming, DP) 是一类优化方法&#xff0c;在给定一个用马尔可夫决策过程 (MDP) 描述的完备环境模型的情况下&#xff0c;其可以计算最优的策…

优化问题笔记(2)

目录 3. 约束优化问题的全局解3.1 凸优化问题3.2 二次优化问题3.3 无约束二次优化问题3.4 一个典型的二次等式约束二次优化问题 Reference 3. 约束优化问题的全局解 3.1 凸优化问题 局部解成为全局解的一类重要的优化问题是所谓凸优化问题. 我们称优化问题 ( f , D ) (f,\ma…

算法-动态规划

动态规划算法 应用场景-背包问题 介绍 动态规划(Dynamic Programming)算法的核心思想是&#xff1a;将大问题划分为小问题进行解决&#xff0c;从而一步步获取最优解的处理算法动态规划算法与分治算法类似&#xff0c;其基本思想也是将待求解问题分解成若干个子问题&#xff0…

Centos7运行pyppeteer报错Browser closed unexpectedly经验总结【必须手动安装谷歌浏览器以自动安装一些依赖】

参考解决方案&#xff1a;pyppeteer.errors.BrowserError: Browser closed unexpectedly - Stack Overflow ldd ~/.local/share/pyppeteer/local-chromium/588429/chrome-linux/chrome | grep not found 注意&#xff1a;安装google-chrome是为了安装这些缺失的so库&#xff0…

针对这两个趋势,3.0全新新零售商业模式可以采取以下策略:

国内市场确实存在“消费升级”和“消费降级”两个趋势&#xff0c;这是由于不同消费者群体的需求和购买力存在差异。消费升级主要发生在高端市场&#xff0c;消费者愿意为高品质、高价值、高价格的商品和服务付出更多。而消费降级则主要发生在中低端市场&#xff0c;消费者更加…

修改antd表单Form.Item的label颜色的方法

默认的Form.item的标签颜色为黑色&#xff0c;但是如果我是用深色背景&#xff0c;这样的情况下表单就看不清楚label了&#xff0c;就像下面的情况&#xff0c;密码两个字完全看不到&#xff0c;所以想把它改为白色字体&#xff0c;就像上面的账号两个字一样&#xff1a; 所以怎…

随笔记录-springboot_LoggingApplicationListener+LogbackLoggingSystem

环境&#xff1a;springboot-2.3.1 加载日志监听器初始化日志框架 SpringApplication#prepareEnvironment SpringApplicationRunListeners#environmentPrepared EventPublishingRunListener#environmentPrepared SimpleApplicationEventMulticaster#multicastEvent(Applicati…

HarmonyOS ArkTS Tab使用方法(十五)

一&#xff0c;使用方法 Android中Java代码使用fragment进行Tab切换&#xff0c;下面使用HarmonyOS ArkTS 语言实现Tab的使用&#xff0c;代码如下&#xff1a; /** Copyright (c) 2022 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "…