Vue3 + Vite 项目搭建

一、Node 及 npm 版本

node 版本需要在 ^18.0.0 || >=20.0.0 区间 nvm 管理 node

  • 查看当前版本
1
2
node -v
npm -v
  • 切换到 20.3.0
1
nvm use 20.3.0 

二、创建项目

使用脚手架创建项目

这个命令会安装和执行 create-vue,它是 Vue 提供的官方脚手架工具。

1
yarn create vue@latest

跟随命令行的提示继续操作,按需求确认是否使用依赖

执行成功后,进入项目目录

1
cd vue3vite/

得到以下目录结构

安装依赖

1
yarn

使用 vue-router 进行路由管理

1
yarn add vue-router

成功后在项目 src 目录下新建 router/index.js 文件, 实现基本功能

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
import { createRouter, createWebHistory } from "vue-router";
import Login from "@/views/Login.vue";
import NotFind404 from "@/views/error/404.vue";
/**
* 白名单,不需要权限也可以访问
*/
export const constantRoutes = [
{
path: "/login",
name: "Login",
component: Login,
meta: { roleId: 0, title: "登录" },
},
{
path: "/404",
name: "404",
component: NotFind404,
meta: { roleId: 0, title: "404页面不存在" },
},
...
];

const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: constantRoutes,
// 是否严格匹配路由
strict: true,
// 路由跳转完成后,页面滚动行为
scrollBehavior: () => ({ left: 0, top: 0 }),
});

export default router;

使用 vuex 进行状态管理

1
yarn add vuex --dev

成功后在项目 src 目录下新建 store/index.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
import { createStore } from "vuex";
import CONFIG from "./module/config";

export default createStore({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {
CONFIG
},
});

使用 axios 统一管理和处理请求

1
yarn add axios

请求封装

创建 request.js 文件

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import axios from "axios";
import router from "@/router";
import { filterUndefined } from "./util";
import { arrayBufferToJson } from "./download";
// 开启 mock 时,访问本地
const baseURL = process.env.Mock ? "" : process.env.API_BASE_URL;
const instance = axios.create({
baseURL,
timeout: 6000,
});

instance.__proto__ = axios;
instance.interceptors.request.use((config) => {
const { params, data } = config;
config.params = params && filterUndefined(config.params);
config.data = data && filterUndefined(config.data);
// 填充 token 到 header 头中
if (localStorage.getItem("token"))
config.headers.Authorization = localStorage.getItem("token");
return config;
});
instance.interceptors.response.use(
(response) => {
let data = response.data;
if (process.env.NODE_ENV === "mock")
response.headers["content-type"] = "application/json; charset=utf-8";
if (response.headers["content-type"].indexOf("application/json") === -1) {
// 下载文件请求,状态码为200时,直接返回成功
return Promise.resolve(data);
} else {
switch (data.code) {
// 请求成功
case 9100:
return Promise.resolve(data);
default:
// 请求参数错误
if (data.code === 9200) {
// 参数错误为联调时期的问题, 不对用户弹窗提示
}
// 9250 用户操作出错 9500 系统繁忙 失败提示弹窗
if (data.code === 9250 || data.code === 9500) {
// 弹窗提示错误msg
}
// 9300 未登录 9400 登录过期 退到登录 弹提示
if (data.code === 9300 || data.code === 9400) {
// 弹窗提示msg
router.push({ name: "Login" }); // 跳转到登录页面
}
// 数据不存在或者已删除
if (data.code === 9404) {
// 弹窗提示msg
router.replace({ name: "404" });
}
return Promise.reject({ ...data, msg: data.msg });
}
}
},
(error) => {
const response = error.response;
let data = null;
try {
const err = response.data.result && response.data.result.error;
// 登录过期/非法、超时
if (err === "timeout" || err === "invalid") {
// 可以弹窗后执行
console.log(err);
}
// 将请求类型为ArrayBuffer的二进制数据转换成json
data = arrayBufferToJson(response.data).data;
} finally {
// let msg = data && data.msg;
// 弹窗 msg 信息
}
// 开发模式才在控制台打印
if (
process.env.NODE_ENV == "development" ||
process.env.NODE_ENV === "mock"
) {
console.warn(error);
}
return Promise.reject(response.data);
}
);
/**
* 执行并发请求
* @param {Array} request 请求方法
* @param {Array} cbs 请求完成后的回调方法
* @return {Promise}
*/
function all(request, cbs) {
return new Promise((resolve, reject) => {
instance
.all(request)
.then(
instance.spread(function () {
let arg = [...arguments];
if (Array.isArray(cbs)) {
cbs.forEach((fn, index) => fn(arg[index]));
}
resolve(arg);
})
)
.catch((err) => {
reject(err);
});
});
}
const get = (url, params, config = {}) =>
instance.get(url, { ...config, params });
const deletes = (url, params, config = {}) =>
instance.delete(url, { ...config, params });
const post = (url, params, config = {}) => instance.post(url, params, config);
const put = (url, params, config = {}) => instance.put(url, params, config);
export default {
get,
deletes,
post,
put,
all,
};

使用 docsify 编写项目文档

  • 全局安装 docsify
1
yarn global add docsify
  • 项目内安装脚手架
1
yarn add docsify-cil
  • 创建文档目录
1
docsify init ./docs
  • 运行文档
1
docsify serve docs

可以写到 package.json

1
2
3
scripts: {
"doc": "docsify serve docs",
}