完整的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仓库拉取代码,代码相对于小白教程的文章有部分优化内容(下图),在教程中没有详细指出,可以参照提交记录学习。

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

一、基础知识准备

一个完整的 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

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

二、增加接口请求模块

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

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

2.1 使用 axios 模块

2.1.1 安装 axios 模块

pnpm i axios

2.1.2 新建 service 文件夹

在 src 下新建 service 文件夹

2.1.3 新建 request.ts

在 service 文件夹下新建 request.ts

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

2.1.4 创建 axios 请求实例

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

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

(2)源代码

import axios, { AxiosInstance } from 'axios'

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

export default createRequestInstance

2.1.5 提交代码

2.2 增加错误处理

2.2.1 新建 error.ts 

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

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

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

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

(3)源代码

import { AxiosError } from 'axios'

// 服务器报错返回 Error 的时候的数据结构,可以和后端商量定义,但是所有接口的格式要统一
export type ErrorResponse = {
	status: number // http 状态码,这个是必须的
	// 其他自定义类型类型
}

class AxiosRequestError extends Error {
	data: ErrorResponse | undefined

	raw: AxiosError

	isUnAuthorized = false // 权限错误 401

	isServerError = false // 服务器错误 500 等

	constructor(status: number, message: string, raw: AxiosError, data?: ErrorResponse) {
		// 调用父类「Error」的构造函数
		super(message)
		this.data = data // 后端返回的 data
		this.raw = raw // axios 返回的原始数据
		this.isUnAuthorized = status === 401
		this.isServerError = status >= 500
		this.message = this.message || '' //给用户展示的错误消息,后续可以自定义
	}
}

export default AxiosRequestError

(4)提交代码

2.2.2 新建 handleError.ts

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

完整的vite + ts + vue3项目,克隆就能用,傻瓜式保姆教程(第二篇)_第8张图片
(2)新增 handleError 方法

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

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

(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 响应的拦截器,对错误进行处理

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

(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, // 允许跨域携带cookie
		baseURL: 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 存放系统中所有的请求地址

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

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

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

(3)源代码

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

 (4)提交代码

2.3.2 封装 API 类

(1)增加 requestList.ts

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

(3)封装 API 类

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

(3) 源代码

import { AxiosRequestConfig, AxiosResponse } from 'axios'
import createRequestInstance from './request'

class API {
	request!: ReturnType

	get!: >(url: string, config?: AxiosRequestConfig) => Promise

	delete!: >(url: string, config?: AxiosRequestConfig) => Promise

	head!: >(url: string, config?: AxiosRequestConfig) => Promise

	options!: >(url: string, config?: AxiosRequestConfig) => Promise

	post!: >(url: string, data?: any, config?: AxiosRequestConfig) => Promise

	put!: >(url: string, data?: any, config?: AxiosRequestConfig) => Promise

	patch!: >(url: string, data?: any, config?: AxiosRequestConfig) => Promise

	constructor(options: { url: string }) {
		const request = createRequestInstance(options.url)
		this.request = request
		this.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

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

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

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

(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 

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

(3)在 App.vue 中调用

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

(4)npm run dev 运行项目

(5)提交代码

2.3.5 测试一下非静态函数

(1)在 App.vue 测试

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

(2)效果

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

 (3)提交代码

2.4 优化请求模块

2.4.1 优化请求地址

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

(1)新建 env.ts

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

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

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

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

(3)修改 request.ts

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

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

(4)修改 requestList.ts

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

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

(5)修改 webRequest.ts 

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

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

(6)测试一下测试环境

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

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

(7)测试一下正式环境

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

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

 (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)导致了修改了三个文件

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

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

三、ts 类型定义

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

3.1 新建 typings 文件夹

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

3.2 新建 index.d.ts

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

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

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 中配置

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

4.1.3 在 main.ts 中引入

import 'virtual:svg-icons-register'

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

 4.1.4 创建 src/images/svgs 文件夹

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

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

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

4.2 使用插件

4.2.1 新建 SvgIcon.vue

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

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

4.2.2 在 login.vue 中使用

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

4.2.3 运行效果

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

4.2.4 提交代码

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

五、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

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

5.1.3 更新 zh.ts & en.ts

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

5.1.4 更新 index.ts

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

5.1.5 在 main.ts 注册

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

5.2 使用多语言

5.2.1 在 login.vue 中使用

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

5.2.2 运行效果

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

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

5.3 提交代码

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

总结

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

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

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

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

你可能感兴趣的:(前端工程化系统教程,vue.js,前端,javascript)