VUE+TS+Pinia+Vant项目搭建1

VUE+TS+Pinia+Vant项目搭建1

创建项目

建议使用pnpm包管理器来创建项目,因为比同类工具更快,更节省空间

image-20240725134308777

使用命令pnpm create vue创建项目,根据需要选择所用的包,本次会使用到TypeScript、Router、Pinia、ESLint、Prettier

设置代码风格

ESLint:代码分析工具,用来检查代码质量

Prettier:代码格式化工具,例如保存时按照标准格式化进行保存

两者合并使用可以在 ESLint 检查代码质量的同时,自动应用 Prettier 的格式化规则。

VSCode提前安装ESLintPrettier - Code formatter插件

设置项目根目录下.prettierrc.json{}

设置项目根目录下.eslintrc.cjs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = {
root: true,
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
},
rules: {
'prettier/prettier': [
'warn',
{
//设置语法规则
singleQuote: true,
semi: false,
printWidth: 80,
trailingComma: 'none',
endOfLine: 'auto'
}
],
'vue/multi-word-component-names': [
'warn',
{
//vue组件为多单词组成,但是要忽略index.vue组件
ignores: ['index']
}
],
//允许结构语法
'vue/no-setup-props-destructure': ['off']
}
}

注意:关闭vscode默认自动保存格式化,在.vscode/settings.json中设置"editor.formatOnSave": false

设置完成后可以执行pnpm lint对所有的文件进行格式标准化

目录调整

image-20240725135954218

路由初始化

在router目录下增加index.ts文件

1
2
3
4
5
6
7
8
9
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
//使用history模式,默认路径为/
history: createWebHistory(import.meta.env.BASE_URL),
routes: []
})
console.log(import.meta)
export default router

上面的BASE_URL默认路径,可以在vite.config.ts中设置,不设置默认为/

image-20240725140424990

在main.ts中引用路由

import router from './router'

app.use(router)

设置移动端适配

安装移动端库Vant,pnpm add vant

在main.ts中引入vant的css,注意要将styles/main.scss文件放在后面,因为我们要将自定义的样式覆盖Vant的样式

image-20240725140827403

进行移动端适配,安装:pnpm add postcss-px-to-viewport -D

新增postcss.config.js文件

1
2
3
4
5
6
7
export default {
plugins: {
'postcss-px-to-viewport': {
viewportWidth: 375
}
}
}

主题定制

我们可以声明css变量来进行主题定制

image-20240725141116957

style/main.css中进行css声明变量

如果想要覆盖元件库中的主题,找到主题变量名,直接覆盖就可以

image-20240725141318128

用户仓库和持久化

pinia建议独立维护

在stores中创建modules目录,在里面增加相应的仓库,如user.ts

安装自动持久化包:pnpm i pinia-plugin-persistedstate

首先要明确user的数据结构,并在types目录下增加user.d.ts

1
2
3
4
5
6
7
export type User = {
token: string
id: string
account: string
mobile: string
avatar: string
}

定义user.ts仓库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import type { User } from '@/types/user'
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useUserStore = defineStore(
'cp-user',
() => {
//用户信息状态
const user = ref<User>()
//设置用户信息
const setUser = (u: User) => {
user.value = u
}
//删除用户函数
const delUser = () => {
user.value = undefined
}
return { user, setUser, delUser }
},
{
//设置持久化
persist: true
}
)

在stroes下的index.ts中,统一导出所有的仓库

1
2
3
4
5
6
import { createPinia } from 'pinia'
import presist from 'pinia-plugin-persistedstate'
//要使用持久化
export const pinia = createPinia().use(presist)
//可以将 所有声明的全部导出
export * from './modules/user'

在main.ts中引入

import { pinia } from './stores'

app.use(pinia)

请求工具设定

在utils目录下增加request.ts文件

1.首先设置基础信息

2.设置请求拦截器

3.设置响应拦截器

4.封装请求函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import router from '@/router'
import { useUserStore } from '@/stores'
import axios, { AxiosError, type Method } from 'axios'
import { showToast } from 'vant'

export const baseURL = 'https://xxx/'
//创建axios实例
const instance = axios.create({
// 1. 基础地址,超时时间
baseURL,
timeout: 10000
})
//请求拦截器
instance.interceptors.request.use(
(config) => {
// 2. 携带token
const store = useUserStore()
if (store.user?.token && config.headers) {
config.headers.Authorization = `Bearer ${store.user.token}`
}
return config
},
(err) => Promise.reject(err)
)
//响应拦截器
instance.interceptors.response.use(
(res) => {
// 3. 处理业务失败,这个10000可以自定义
if (res.data.code !== 10000) {
// 错误提示
showToast(res.data.message || '业务失败')
// 返回 错误的promise
return Promise.reject(res.data)
// 传入 code 将来catch的时候可以使用
}
// 4. 摘取核心响应数据-数据剥离
return res.data
},
(err: AxiosError) => {
// 5. 处理401错误
if (err.response?.status === 401) {
// 清除本地的用户信息
const store = useUserStore()
store.delUser()
// 跳转到登录页面,携带当前访问页面的地址(包含参数的)
router.push({
path: '/login',
query: { returnUrl: router.currentRoute.value.fullPath }
})
}
return Promise.reject(err)
}
)
//导出实例
export default instance
//数据类型,要根据后端接口来定
type Data<T> = {
code: number
message: string
data: T
}
//封装调用函数,并用泛型的形式
export const request = <T>(
url: string,
method: Method = 'GET',
submitData?: object
) => {
// 参数:地址,请求方式,提交的数据
// 返回:promise
//request<T=any,R=AxiosResponse<T>,D=any>
//T:返回结果res.data类型
//R:返回结果res类型
//D:post请求提交给data参数的类型
return instance.request<any, Data<T>>({
url,
method,
//根据出入的方法,自动判断用啥参数,该处使用[]
[method.toUpperCase() === 'GET' ? 'params' : 'data']: submitData
})
}

使用请求工具

image-20240725150541123

VUE+TS+Pinia+Vant项目搭建1

https://bubuweiying.site/VUE项目搭建1/

作者

步步为营

发布于

2024-07-25

更新于

2025-03-15

许可协议