news 2026/7/18 13:38:16

阶段三:Axios 与 Express 前后端通信

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
阶段三:Axios 与 Express 前后端通信

从零构建带AI流式对话的Vue2全栈应用-CSDN博客本文是对这篇文章阶段三的讲解

一、阶段三解决什么问题

阶段二的数据写死在前端:

users: [ { id: 1, name: '张三' } ]

这种数据刷新后不会真正变化,也不是从服务器获取。

阶段三开始让数据来自后端:

Vue 页面 ↓ 请求 Express 后端 ↓ 返回 JSON Vue 页面显示结果

核心技术:

HTTP REST API Express Axios Vue 开发代理 请求拦截器 响应拦截器 async/await

二、Express 后端基础

文件:

mock-server/server.js

顶部:

const express = require('express') const app = express() const PORT = 3000

1.require('express')

const express = require('express')

从已经安装的express软件包中读取 Express。

Express 是一个 Node.js 后端框架。

它能帮助我们处理:

GET 请求 POST 请求 PATCH 请求 DELETE 请求 JSON 数据 URL 参数

2. 创建服务器对象

app可以理解成后端服务器。

后面所有接口都写在app上:

app.get(...) app.post(...) app.patch(...) app.delete(...)

3. 设置端口

const PORT = 3000

后端运行后地址是:

http://localhost:3000

localhost表示当前电脑。

3000表示端口。

端口可以理解成一栋楼里的房间号:

localhost:这台电脑 3000:后端程序所在房间 8081:前端程序所在房间

4. 解析 JSON 请求体

app.use(express.json())

前端发送:

{ "name": "张三", "email": "zhangsan@example.com" }

Express 需要把这段 JSON 转成 JavaScript 对象。

有了express.json(),后端才能使用:

req.body.name req.body.email

没有这一行,req.body可能是undefined


三、模拟数据库

let users = [ { id: 1, name: '张三', email: 'zhangsan@example.com', role: 'admin', status: true } ]

这里暂时没有真正数据库。

使用数组模拟数据库。

users 数组 ≈ 用户表 数组中的对象 ≈ 数据库中的一行

因为使用的是内存数组:

新增用户后可以暂时看到 后端重启后数据恢复

这是教学阶段的正常现象。


四、GET 查询接口

app.get('/api/users', (req, res) => { res.json({ code: 0, message: '获取用户列表成功', data: users }) })

app.get

表示处理 GET 请求。

前端请求:

GET /api/users

后端进入这个函数。


reqres

(req, res) => {}

req是 request,请求。

里面有:

req.query:查询参数 req.params:路径参数 req.body:请求体 req.headers:请求头 req.cookies:Cookie

res是 response,响应。

常用方法:

res.json() res.status() res.send() res.redirect()

返回统一格式

res.json({ code: 0, message: '获取用户列表成功', data: users })

统一返回格式:

code:业务状态 message:提示信息 data:真正的数据

成功:

code: 0

失败:

code: 400 code: 401 code: 404 code: 500

五、查询参数

前端请求:

/api/users?keyword=张三&role=admin

后端读取:

req.query.keyword req.query.role

代码:

const keyword = String( req.query.keyword || '' ) .trim() .toLowerCase()

逐步解释:

req.query.keyword || ''

表示有关键词就使用关键词,没有就使用空字符串。

String(...)

确保它是字符串。

.trim()

去掉前后空格。

例如:

" 张三 "

变成:

"张三"
.toLowerCase()

转成小写,方便不区分大小写搜索。


六、数组筛选

const result = users.filter(user => { return user.name.includes(keyword) })

filter()用于筛选数组。

它会逐个检查用户。

return true

保留这个用户。

return false

删除这个用户。

例如:

users.filter(user => { return user.role === 'admin' })

只保留管理员。


七、POST 新增接口

app.post('/api/users', (req, res) => { const name = req.body.name const email = req.body.email const newUser = { id: nextUserId, name, email } nextUserId += 1 users.unshift(newUser) res.status(201).json({ code: 0, message: '新增成功', data: newUser }) })

POST 和 GET 的区别

GET 通常用于查询:

GET /api/users

POST 通常用于新增:

POST /api/users

新增的数据放在请求体中。


users.unshift(newUser)

users.unshift(newUser)

把新用户放到数组最前面。

如果使用:

users.push(newUser)

则会放到最后面。


状态码 201

res.status(201)

HTTP 状态码:

200:请求成功 201:创建成功 400:参数错误 401:没有登录 403:没有权限 404:找不到资源 500:服务器错误

八、PATCH 修改状态

路由:

app.patch('/api/users/:id/status', ...)

其中:

:id

是动态路径参数。

请求:

PATCH /api/users/3/status

后端读取:

req.params.id

得到字符串:

"3"

转换为数字:

const userId = Number(req.params.id)

然后查找用户:

const user = users.find(item => { return item.id === userId })

find()找到第一个符合条件的对象。


九、DELETE 删除用户

const userIndex = users.findIndex(item => { return item.id === userId })

findIndex()返回数组下标。

例如张三在第一个位置:

userIndex === 0

删除:

users.splice(userIndex, 1)

含义:

从 userIndex 位置开始 删除 1 个元素

十、为什么 404 必须放在最后

app.use((req, res) => { res.status(404).json({ code: 404, message: '接口不存在' }) })

Express 从上往下匹配代码。

正确顺序:

GET /api/users POST /api/users PATCH /api/users/:id/status DELETE /api/users/:id 最后处理 404

如果把 404 放最前面:

所有请求都会先匹配 404 后面的接口永远不会执行

十一、Vue 代理vue.config.js

module.exports = defineConfig({ devServer: { proxy: { '^/api': { target: 'http://localhost:3000', changeOrigin: true } } } })

前端代码请求:

/api/users

浏览器实际访问前端服务器:

http://localhost:8081/api/users

Vue 开发服务器发现路径以/api开头,然后转发:

http://localhost:3000/api/users

代理流程:

浏览器 ↓ /api/users Vue 开发服务器 8081 ↓ 转发 Express 后端 3000

十二、Axios 实例request.js

const service = axios.create({ baseURL: '/api', timeout: 10000 })

baseURL

调用:

request({ url: '/users' })

Axios 会组合成:

/api/users

timeout

timeout: 10000

单位是毫秒。

10000 毫秒 = 10 秒

如果后端 10 秒都没有响应,Axios 会认为超时。


十三、请求拦截器

service.interceptors.request.use( config => { console.log(config) return config }, error => { return Promise.reject(error) } )

请求拦截器会在请求真正发出之前执行。

流程:

页面调用 getUsers() ↓ 进入请求拦截器 ↓ 可以修改请求头、打印日志 ↓ 发送到后端

为什么一定要:

return config

因为 Axios 需要继续使用这个请求配置。

不返回,后续请求可能无法正常发出。


十四、响应拦截器

后端返回:

{ "code": 0, "message": "成功", "data": [ { "id": 1 } ] }

响应拦截器:

return responseBody.data

所以页面最终得到的不是整个对象,而是:

[ { id: 1 } ]

页面可以直接:

this.users = result

而不用:

this.users = result.data.data

十五、API 文件user.js

export function getUsers(params) { return request({ url: '/users', method: 'get', params }) }

为什么不直接在页面写 Axios?

因为把接口集中放在src/api中更容易管理。

页面只关心:

getUsers() createUser() deleteUser()

不需要反复写:

axios.get(...) axios.post(...)

这是代码分层:

页面层:控制页面显示 API 层:描述调用哪个接口 request 层:统一处理 Axios 后端层:处理真实业务

十六、created()生命周期

created() { this.fetchUsers() }

created()是 Vue 生命周期钩子。

组件创建完成时自动执行一次。

所以进入页面后,会自动加载用户列表。

不需要用户先点击“查询”。


十七、async/await

async fetchUsers() { const result = await getUsers() this.users = result }

接口请求需要时间,不会立刻返回。

await表示:

等待请求完成,再继续往下执行。

使用await的函数前必须有:

async

错误:

fetchUsers() { const result = await getUsers() }

正确:

async fetchUsers() { const result = await getUsers() }

十八、try/catch/finally

async fetchUsers() { this.loading = true try { this.users = await getUsers() } catch (error) { this.$message.error('加载失败') } finally { this.loading = false } }

执行过程:

开始请求 loading = true ↓ 成功:进入 try 失败:进入 catch ↓ 无论成功失败,都进入 finally loading = false

所以finally非常适合关闭加载动画。


十九、阶段三完整数据流

ApiDemoView.vue 调用 getUsers() ↓ src/api/user.js 配置 GET /users ↓ src/utils/request.js 添加 baseURL /api ↓ 请求 /api/users ↓ Vue 代理到 localhost:3000 ↓ Express app.get('/api/users') ↓ 返回 JSON ↓ 响应拦截器提取 data ↓ this.users = result ↓ el-table 自动更新
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/18 13:37:39

期货Level2与股票逐笔行情数据有什么,如何下载

期货Level2与股票逐笔行情数据有什么 昨晚跑因子策略又内存溢出了,查了半天发现是历史Tick数据太大了,一个合约一年下来几十个G。今天索性把数据源翻了个底朝天,看看那个下载页面上到底有哪些东西,免得下次再踩坑。 数据分哪几类&…

作者头像 李华
网站建设 2026/7/18 13:34:53

AI-Shoujo HF Patch:模块化增强套件深度解析与实战指南

AI-Shoujo HF Patch:模块化增强套件深度解析与实战指南 【免费下载链接】AI-HF_Patch Automatically translate, uncensor and update AI-Shoujo! 项目地址: https://gitcode.com/gh_mirrors/ai/AI-HF_Patch AI-Shoujo HF Patch是一款专为AI-Shoujo游戏设计的…

作者头像 李华
网站建设 2026/7/18 13:34:18

OpenClaw智能代理框架Windows安装与配置指南

1. OpenClaw简介与Windows安装价值OpenClaw作为一款新兴的跨平台智能代理框架,正在开发者社区掀起热潮。它最吸引人的特性是能将AI能力无缝融入操作系统层面,通过简单的指令就能控制屏幕、摄像头、通知系统等硬件资源。不同于常规的聊天机器人&#xff0…

作者头像 李华
网站建设 2026/7/18 13:34:09

Three.js 花瓣雨教程

花瓣雨 Flower Rain ▶ 在线运行案例 案例合集: 三维可视化功能案例(threehub.cn)开源仓库github地址: https://github.com/z2586300277/three-cesium-examples400个案例代码: 网盘链接 你将学到什么 OrbitControls 相机轨道…

作者头像 李华
网站建设 2026/7/18 13:32:37

AM62L CBASS防火墙配置详解:从硬件隔离到系统安全实践

1. 从硬件防火墙到系统安全:AM62L的CBASS防火墙深度解析在嵌入式系统,尤其是汽车电子和工业控制这类对功能安全和信息安全有严苛要求的领域,硬件防火墙早已不是“锦上添花”的选项,而是构建系统可信基石的“必需品”。它就像一座建…

作者头像 李华
网站建设 2026/7/18 13:31:36

YimMenu终极指南:3步打造GTA5最安全的游戏体验

YimMenu终极指南:3步打造GTA5最安全的游戏体验 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/yi/YimMenu …

作者头像 李华