第一次前后端联调后,我终于理解了什么是工程化

以前我认为前端就是写写页面、改改样式,至于数据咋来的,那不都是后端的事吗?前端只需要渲染数据不就行了?

然而大错特错,恰恰是这个数据,就是前后端联调的关键。

真正开发其实是: 前端 + 后端 + 数据 + 接口 + 协作

我之前写的项目都是静态页面,从来没有真正接入真实数据,当我开始做大项目时就发现问题了。

如果只是闷头写数据,你连数据类型都不知道,你怎么写?

所以首先就要去翻接口文档,看看后端传过来的数据是什么,格式如何,类型如何,才能正确渲染数据。

当然,只是成功接收数据还是远远不够的,对于我们这种前端都半桶水的新手,要先了解后端到底干了什么,数据是怎样流动的。

数据流动方向:

js 复制代码
React页面
   ↓
axios/fetch
   ↓
HTTP请求
   ↓
Node/FastAPI
   ↓
MySQL
   ↓
JSON返回
   ↓
前端渲染

下面我用一个小demo简单说明前后端联调的过程。

我们先从后端开始,自己写一个接口,其实后端没有想象中那么难。我们可以用node.js来写后端代码,用的就是javascript语言,学习成本比较低。

首先建立一个server文件夹,写入index.js文件。创建express服务器和cors中间件(前后端跨域),再定义post和get的API即可完成一个简单的后端接口。

js 复制代码
const express = require("express");
const cors = require("cors");
const jwt = require("jsonwebtoken");

const app = express();

const SECRET_KEY = "your_secret_key";

const user = {
  id: 1,
  username: "admin",
  password: "qwiqdqd90090",
};

app.post("/login", (req, res) => {
  const { username, password } = req.body;
  if (username === user.username && password === user.password) {
    //登录成功,生成token
    const token = jwt.sign({ id: 1, username: "admin" }, SECRET_KEY, {
      expiresIn: "1h", //token有效期为1小时,防止token泄露别人可以永久登录你的账号
    });
    return res.json({
      code: 0,
      data: { token },
    });
  } else {
    return res.status(401).json({ message: "Invalid credentials" });
  }
});

app.get("/user", authMiddleware, (req, res) => {
  return res.json({
    id: req.user.id,
    username: req.user.username,
  });
});

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});

再加入鉴权中间件,这个是jwt用来进行身份认证的内容。token用来维持用户状态。

js 复制代码
// 鉴权中间件
function authMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader) return res.status(401).json({ message: "未登录" });

  const token = authHeader.split(" ")[1];

  try {
    const decoded = jwt.verify(token, SECRET_KEY);
    req.user = decoded;
    next();
  } catch {
    return res.status(401).json({ message: "token无效或已过期" });
  }
}

完成后我们启动后端,看到输出Server is running on port 3000则成功,表示后端在端口3000运行。

js 复制代码
node index.js

接下来通过Postman来测试后端接口是否正常,Postman可以模拟前端请求,看到后端的返回信息,常用于测试接口是否正确。

Postman 最大的意义,

其实是:

把"前端问题"和"后端问题"分离。

因为:

如果 Postman 都请求失败,

那问题一定在后端。

如果 Postman 成功,但前端失败,

那问题就在前端请求逻辑。

我们首先登录,获取鉴权token,根据后端接口知道,登录接口是post,前端提交username和password,通过认证后后端返回{ code: 0, data: { token }, }。所以我们在请求时选择POST请求login接口,并且在请求体body中写入username和password。成功返回200,以及code,token。

现在复制token到请求头Headers,添加Authorization,内容为Bearer token值(jwt鉴权格式)。换成GET请求user接口,返回user信息即为成功。

现在初始化前端项目,新建utils文件夹,写入request.js文件,使用axios 全局封装 ,专门用来解决前后端分离项目中重复的请求配置统一的认证 / 错误处理问题。

axios 封装真正解决的是

统一整个项目的请求行为。

比如:

  • 自动携带 token
  • 统一错误处理
  • 统一 baseURL
  • 统一 loading
  • 统一超时逻辑

这些都是工程化开发里的基础,因为,工程化=统一。

js 复制代码
import axios from "axios";

const request = axios.create({
  baseURL: "http://localhost:3000",
});

//请求拦截器
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, // 2xx 成功,直接把数据给你
  (error) => {
    if (error.response && error.response.status === 401) {
      const requestUrl = error.config?.url || "";
      if (requestUrl !== "/login") {
        alert("登录已过期,请重新登录");
        localStorage.removeItem("token");
      }
    }
    return Promise.reject(error);
  },
);

export default request;

再写一个简单的前端页面App.js

js 复制代码
import { useState, useEffect } from "react";
import request from "./utils/request";
import "./App.css";

function App() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [loggedIn, setLoggedIn] = useState(false);
  const [userInfo, setUserInfo] = useState(null);

  useEffect(() => {
    const token = localStorage.getItem("token");
    if (token) {
      setLoggedIn(true);
    }
  }, []);

  async function handleLogin(event) {
    event.preventDefault();
    const trimmedUsername = username.trim();
    const trimmedPassword = password.trim();
    if (!trimmedUsername || !trimmedPassword) {
      alert("请输入用户名和密码");
      return;
    }
    try {
      //await 把异步的 reject 拉回到当前同步流里,变成了同步错误
      const response = await request.post("/login", {
        username: trimmedUsername,
        password: trimmedPassword,
      });
      if (response.data.code === 0) {
        localStorage.setItem("token", response.data.data.token);
        setLoggedIn(true);
        alert("登录成功");
      } else {
        alert("登录失败:" + response.data.message);
      }
    } catch (error) {
      const message =
        error.response?.data?.message || error.message || "未知错误";
      alert("请求失败:" + message);
    }
  }

  async function fetchUserInfo() {
    try {
      const response = await request.get("/user");
      setUserInfo(response.data);
    } catch (error) {
      const message =
        error.response?.data?.message || error.message || "未知错误";
      alert("获取用户信息失败:" + message);
    }
  }

  return (
    <form className="App">
      <input
        type="text"
        placeholder="请输入用户名"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <input
        type="password"
        placeholder="请输入密码"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button type="button" onClick={handleLogin}>
        登录
      </button>
      <button type="button" onClick={fetchUserInfo} disabled={!loggedIn}>
        获取用户信息
      </button>

      {loggedIn && <p>✅ 已登录</p>}

      {userInfo && (
        <div
          style={{ marginTop: "20px", background: "#f0f0f0", padding: "10px" }}
        >
          <h3>用户信息:</h3>
          <p>ID: {userInfo.id}</p>
          <p>用户名: {userInfo.username}</p>
        </div>
      )}
    </form>
  );
}

export default App;

点击登录即可登录成功(POST请求login)

点击获取用户信息(GET请求user)

这样一个前后端分离的小demo就完成啦,不过这里没有写数据库的内容,直接在后端定义了user列表。

写完这个 demo 后, 我第一次真正理解:

前后端联调并不是"接口调通"这么简单。

它背后其实涉及:

  • HTTP 请求
  • 数据流
  • 接口规范
  • 登录鉴权
  • 状态管理
  • 错误处理
  • 前后端协作

工程化不是突然出现的高级概念。

而是:

从第一次真正接入真实数据开始。

相关推荐
亲亲小宝宝鸭1 小时前
Vue3中那些冷门但实用的方法
前端·vue.js
qq_349523261 小时前
分析原型到表的过程
前端
1 小时前
Pinia 全局状态管理
前端
M ? A1 小时前
Vue 转 React | VuReact 实时监听开发指南
前端·vue.js·后端·react.js·面试·开源·vureact
陆枫Larry1 小时前
uni-app 小程序:滚动联动透明导航栏的实现
前端
半兽先生1 小时前
vue高性能下拉组件 支持上万数据不卡顿
前端·javascript·vue.js
懂懂tty1 小时前
Vue3 架构
前端·vue.js
invicinble1 小时前
前端框架使用vue-cli( 第二层:工程配置层--总览)
前端·vue.js·前端框架
哆啦A梦15882 小时前
01, 前端vue3框架的快速搭建以及项目工程的讲解
前端·vue3·springboot