一、问题描述
- 用
axios.post()直接传对象,后端收不到数据。 - 原因是 axios 默认会把 POST 数据序列化为 JSON 格式 ,而很多后端(尤其是老项目)默认只识别
application/x-www-form-urlencoded格式(即表单格式)。 - 所以数据被 "拦截" 了,本质是前后端数据格式不兼容,而不是 axios 主动拦截
二、代码示例:为什么直接传对象不行?
- 错误写法(后端收不到数据)
js
// 错误示例:直接传对象
axios.post('/api/login', {
username: 'admin',
password: '123456' }).then(res => {
console.log(res)
}).catch(err => {
console.error(err)
})
问题分析
- axios 默认设置
Content-Type: application/json,发送的是 JSON 字符串:
json
{ "username": "admin", "password": "123456" }
- 如果后端是用 PHP、Java 等传统方式读取
$_POST或request.getParameter(),它们默认只解析application/x-www-form-urlencoded格式,所以读不到 JSON 里的字段,表现为 "数据传不过去"。
三、正确的解决方案(代码实现)
方案一:使用 qs 库,将数据转为表单格式(推荐)
这是最稳妥的方式,和后端传统表单提交格式完全一致。
- 安装 qs
bash
npm install qs --save
- 封装请求(推荐写法)
js
import axios from 'axios'
import qs from 'qs'
// 创建实例
const request = axios.create({
baseURL: '/api',
timeout: 5000
})
// 请求拦截器:统一处理 POST 数据格式
request.interceptors.request.use(config => {
// 只对 POST 请求做处理
if (config.method === 'post' && config.data) {
// 将 JSON 对象转为 application/x-www-form-urlencoded 格式
config.data = qs.stringify(config.data)
// 同时修改 Content-Type 头(有些后端需要明确指定)
config.headers['Content-Type'] = 'application/x-www-form- urlencoded'
}
return config
}, error => {
return Promise.reject(error)
})
// 使用
request.post('/login', {
username: 'admin',
password: '123456'
})
发送的数据格式:
plaintext
username=admin&password=123456
后端可以直接用 $_POST['username'] 或request.getParameter("username") 读取。
方案二:手动设置 FormData(适合上传文件或混合数据)
js
const formData = new FormData()
formData.append('username', 'admin')
formData.append('password', '123456')
axios.post('/api/login', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
适用场景
- 需要上传文件(
File对象) - 混合文本和文件数据
方案三:让后端支持 JSON 格式(现代项目首选)
如果后端是 Node.js(Express),可以直接用中间件解析 JSON:
js
// 后端 Express 示例
const express = require('express')
const app = express()
// 解析 JSON 格式的请求体
app.use(express.json())
// 现在就能直接读取 req.body.username 了
app.post('/api/login', (req, res) => {
const { username, password } = req.body
res.send({ username, password })
})
前端代码就可以保持最简洁的写法:
js
axios.post('/api/login', {
username: 'admin',
password: '123456'
})
四、总结:为什么说 "axios 有拦截功能"?
这句话其实是对 "默认行为" 的误解:
- axios 并没有主动 "拦截" 你的数据,而是自动做了序列化 :
- GET 请求:自动把参数拼到 URL 上。
- POST 请求:默认把对象转为 JSON,并设置
Content-Type: application/json。
- 当后端不支持这种格式时,数据就 "传不过去",看起来像是被拦截了。
最佳实践:
- 新项目:前后端统一使用 JSON 格式,后端配置
express.json()等中间件。 - 老项目:用
qs统一转为表单格式,避免逐个接口处理。