Vue 路由、状态管理与接口分层实战
Vue 路由、状态管理与接口分层实战
后端同学在 Vue 项目里最应该先打通的是三条线:
- 页面路由怎么走。
- 状态数据放哪里。
- 接口请求如何统一治理。
打通这三条线,绝大多数中后台需求都能接住。
一、路由设计:按业务模块拆
router/modules/user.ts 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import type { RouteRecordRaw } from "vue-router";
const userRoutes: RouteRecordRaw[] = [
{
path: "/users",
name: "UserList",
component: () => import("@/views/user/UserList.vue"),
meta: {
title: "用户管理",
permission: "user:list"
}
}
];
export default userRoutes;
meta.permission 可以和后端权限点做映射,便于统一权限控制。
二、路由守卫:统一处理登录态和权限
router/guard.ts 示例:
1
2
3
4
5
6
7
8
9
10
11
router.beforeEach((to, _from, next) => {
const token = localStorage.getItem("token");
if (!token && to.path !== "/login") {
next("/login");
return;
}
// 这里可扩展权限点判断
next();
});
注意:权限判断最好放守卫或专门的权限工具里,不要散落在每个页面里。
三、状态管理:只存“共享状态”
stores/user.ts 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { defineStore } from "pinia";
interface UserState {
token: string;
nickname: string;
}
export const useUserStore = defineStore("user", {
state: (): UserState => ({
token: "",
nickname: ""
}),
actions: {
setToken(token: string) {
this.token = token;
}
}
});
不要把页面私有表单状态也放进 store,否则状态边界会越来越模糊。
四、接口层分层:页面不直接碰 axios
推荐分层:
utils/request.ts:统一 axios 实例与拦截器。api/modules/*.ts:具体业务接口。views/*.vue:只调用api,不关心底层细节。
utils/request.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 axios from "axios";
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000
});
request.interceptors.request.use((config) => {
const token = localStorage.getItem("token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
request.interceptors.response.use(
(response) => response.data,
(error) => {
// 这里可统一错误码处理
return Promise.reject(error);
}
);
export default request;
五、类型定义:接口契约前置
types/user.ts:
1
2
3
4
5
6
7
8
9
10
export interface UserItem {
id: number;
username: string;
status: "ENABLED" | "DISABLED";
}
export interface PageResult<T> {
list: T[];
total: number;
}
api/modules/user.ts:
1
2
3
4
5
6
import request from "@/utils/request";
import type { PageResult, UserItem } from "@/types/user";
export function queryUsers(params: { pageNo: number; pageSize: number }) {
return request.get<PageResult<UserItem>>("/users", { params });
}
六、错误处理建议
- 网络错误:统一提示“网络异常,请稍后重试”。
- 401:跳转登录并清理本地登录态。
- 403:提示无权限并上报埋点。
- 500:展示可追踪的错误编号,方便后端排查。
七、后端同学的加分动作
- 主动定义分页返回结构统一规范(
list/total)。 - 统一时间字段格式(UTC / 时区 / 展示格式)。
- 统一空值语义(
null、""、[]的业务含义)。
八、实战检查清单
- 新路由是否按模块独立维护。
- 是否只有
api层直接依赖 axios。 - store 是否只存跨页面共享状态。
- 页面是否避免重复错误处理代码。
这套分层做好后,你的前端改动会像后端分层一样可维护、可演进。
本文由作者按照 CC BY 4.0 进行授权