开头:今天学了一个全栈项目的"协作心法"------前后端分离下的前端接口工程 。以前我总觉得:前端要等后端把接口写好了,才能开始开发。结果老师说:"傻等后端给接口?前端完全没必要等!" 前端自己定义接口、自己 mock 数据、自己先跑起来,等后端接口真正写好了,把
baseURL一键切换过去就行。听完我悟了------前后端分离,不只是"代码分开",更是"开发节奏解耦"。
一、前后端分离的"三驾马车"
1.1 前端独立开发
老师说:
"前端项目独立开发的三驾马车:组件(响应式)+ 路由 + 状态管理(银行)。"
swift
前端三驾马车
├── 组件:React(响应式 UI)
├── 路由:react-router(页面切换)
└── 状态管理:zustand(数据"银行")
这三个东西组合起来,前端本身就是一个完整的应用------不需要后端也能独立开发。
1.2 前后端的"唯一耦合点"
老师说:
"
/api接口请求------前后端分离的了吗?唯一一个耦合。前端要等着后端提供的接口,渲染数据状态。"
前后端代码可以完全分开,但"数据接口"是它们唯一的连接点:
bash
前端(React)─── /api/todos 接口 ─── 后端(Node/Koa)
这个唯一的耦合点,就是"前端接口工程"要解决的问题。
二、前端为什么需要 api 目录?
2.1 痛点:后端接口常常不及时
老师说:
"后端接口往往不能及时提供。前端接口层------管理所有的接口,axios 配置,先伪造数据,
baseURL一键切换。前端工程里的一环,既 API 工程。"
如果前端傻等后端接口:
bash
前端:等后端写 /api/todos 接口......
后端:还在写别的需求......
前端:页面写不了,干等!
有了"前端接口层":
bash
前端:先自己定义 /api/todos,用 mock 数据!
后端:慢慢写真实接口,不着急!
前端:页面正常开发,完全不等!
2.2 api 目录的职责
看 todos.js:
javascript
// 一个模块一个 JS 文件
import axios from './config';
// api 目录的职责:不是直接就去后端,有时候后端没有开发好,和我们分离
export const getTodos = async () => {
const res = await axios.get('/todos');
return res.data;
};
api 目录是"前端接口的统一管理入口":
| 特点 | 说明 |
|---|---|
| 一个模块一个文件 | todos.js 管 todos 接口,user.js 管用户接口 |
| 统一出口 | 所有接口函数集中管理,好找好改 |
| 不直接打后端 | 先走 mock,等后端好了再切换 |
三、axios 配置:baseURL 一键切换
3.1 为什么用 axios?
看 config.js:
javascript
import axios from 'axios';
// 实例化 axios
// fetch 缺点是功能小
// app /api/todos -> http://localhost:3000/todos
// 统一管理,fetch 升级为 axios
const instance = axios.create({
baseURL: '/api', // dev:前端模拟的请求地址 /api/todos
// baseURL: 'http://localhost:3000', // prod:真实后端地址(注释备用)
timeout: 5000,
});
export default instance;
老师说:
"Fetch 缺点是功能小。App 应用升级到 axios------统一管理。"
axios 比 fetch 强在哪?
| 对比 | fetch | axios |
|---|---|---|
| 超时设置 | 要自己封装 AbortController | timeout: 5000 一行搞定 |
| 拦截器 | 没有 | 有(请求/响应拦截器) |
| baseURL | 要手动拼接 | 配置一次全局生效 |
| 错误处理 | 手动判断 | 统一 error 处理 |
3.2 baseURL 一键切换的秘密
config.js 里的两行 baseURL:
javascript
baseURL: '/api', // 开发阶段:走 mock
// baseURL: 'http://localhost:3000', // 联调阶段:走后端
切换只需注释/取消注释一行!
bash
开发阶段:
前端请求 /api/todos
↓(mock 拦截)
返回 mock 数据
联调阶段:
注释掉 '/api',启用 'http://localhost:3000'
前端请求 http://localhost:3000/todos
↓
返回后端真实数据
这就是"一键切换"------前后端分离的节奏就这样解耦了。
四、Mock 数据:前端先跑起来
4.1 为什么要 mock?
老师说:
"前端需要数据状态,由数据接口提供。不能直接走后端数据接口(前后端分离,不掉不一致)。前端也需要独立完备整个应用开发工程系统,纳入了前端接口工程。"
前端开发不能依赖后端的进度------mock 就是前端自己的"假后端"。
4.2 mockjs + Vite 配置
老师说:
"MockJS + Vite 配置------mock 目录:
export default [{ url: '/api/todos', method: 'get', response: [...] }]。"
javascript
// mock/todos.js(示意)
export default [
{
url: '/api/todos',
method: 'get',
response: [
{ id: 1, text: '学习 React', completed: false },
{ id: 2, text: '学习路由', completed: false },
]
}
];
mock 目录的作用:前端请求 /api/todos 时,Vite 的 mock 插件拦截请求,返回这段假数据。
五、页面 + 接口完整流程
5.1 Todos 页面
看 Todes.jsx:
jsx
import { getTodos } from '../api/todos';
import { useEffect, useState } from 'react';
function Todos() {
const [todos, setTodos] = useState([]);
useEffect(() => {
// IIFE 立即执行函数
(async () => {
const data = await getTodos();
setTodos(data);
})();
}, []);
return <h1>Todos</h1>;
}
页面获取数据的标准流程:
scss
组件挂载
↓ useEffect([] 只执行一次)
getTodos() ← 调用 api 目录的接口函数
↓ axios 请求
/api/todos ← baseURL('/api') + 路径('/todos')
↓ mock 拦截(开发阶段)
返回假数据
↓ setTodos(data)
响应式更新页面
5.2 路由配置
看 App.jsx:
jsx
import React, { lazy, Suspense } from 'react';
import { Routes, Route, BrowserRouter as Router } from 'react-router-dom';
import Nav from './components/Nav';
const Home = lazy(() => import('./pages/Home'));
const Todos = lazy(() => import('./pages/Todes'));
function App() {
return (
<Router>
<Nav />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/todos" element={<Todos />} />
</Routes>
</Router>
);
}
这里用到了之前学的所有路由知识:BrowserRouter、Routes/Route、lazy 懒加载、Link 导航(Nav 里)。
六、完整架构图
bash
前端(独立应用)
├── 页面路由:pages/(Home、Todos)── react-router
├── 组件:components/(Nav)── React 组件化
├── 接口层:api/(todos.js)── axios 统一管理
│ └── config.js:axios 实例 + baseURL
├── mock 数据:mock/(开发阶段假接口)
└── 状态管理:zustand(数据"银行")
↓ /api 接口(唯一耦合点)
后端(Node/Koa)
└── 真实接口:/todos 返回 JSON
前后端协作的关键:前端通过 /api 接口层和后端对接,开发阶段用 mock,联调阶段切 baseURL。
七、总结:前端接口工程
| 概念 | 说明 |
|---|---|
| 前后端分离 | 前端三驾马车(组件+路由+状态管理)独立开发 |
| 唯一耦合点 | /api 接口 |
| api 目录 | 前端接口统一管理,一个模块一个文件 |
| axios | 升级版请求库,baseURL/timeout/拦截器 |
| baseURL 切换 | 开发用 /api(mock),联调换真实地址 |
| mock 数据 | 前端自己造假数据,不等后端 |
| 开发节奏解耦 | 前端后端各干各的,接口好了再联调 |
前端接口工程的核心思想:前端不要傻等后端接口------自己定义接口层、自己 mock 数据、自己跑通整个应用,等后端接口好了,一键切换 baseURL 就行。这就是前后端分离的真正价值:开发节奏解耦,效率翻倍。
写在最后
今天最大的收获,是理解了"前端接口工程"这个思路。以前总觉得"前端等后端"是天经地义的,现在知道了------前端完全可以先跑起来,mock 数据就是前端的"假后端"。等真后端好了,改一行 baseURL 就切换过去。
而且今天把之前学的东西全串起来了:路由(lazy + Routes)、axios 配置、useEffect 异步请求、模块化目录(api/pages/components)......一套全栈项目的心法,齐活了。
下次面试官问你:"前后端分离时,前端怎么不等后端接口?"
你可以淡定地说:
"前后端分离时,前端通过建立'接口工程'实现不等后端。具体做法:① 在 api/ 目录统一管理所有接口函数(如 getTodos()),一个模块一个文件;② 配置 axios 实例,baseURL: '/api' 指向开发环境的 mock 服务;③ 用 MockJS 在 mock 目录里定义假接口数据,前端请求 /api/todos 时由 Vite 拦截返回 mock 数据,页面正常开发;④ 等后端真实接口完成后,把 baseURL 一键切换为真实地址(如 http://localhost:3000)即可完成联调。这样前端和后端开发节奏完全解耦,互不阻塞。"
然后看着面试官满意的表情,心里默念:这波,又稳了。
本文所有代码示例均来自课堂学习资料,真实可运行。