Axios 中 params 与 data 的区别与原理
一、核心区别
Axios 中 params 和 data 决定参数放在 HTTP 请求的不同位置:
| 配置 | 参数位置 | 实际效果 | 适用场景 |
|---|---|---|---|
params |
URL 查询字符串(Query String) | POST /xxx?foo=1&bar=2 |
传少量简单参数,如 ID、分页、筛选条件 |
data |
请求体(Request Body) | Body 中发送 JSON:{"foo":1,"bar":2} |
传复杂对象、列表、批量数据 |
二、具体示例
实际代码对比
ts
// 写法一:参数拼到 URL 上
export function printSkuPackageCodeList(data: any) {
return request({
url: '/api/save',
method: 'post',
params: data, // data 的内容会被拼到 URL ?key=value
});
}
// 写法二:参数放到请求体里
export function sampleBuyOrderPrint(params: any) {
return request({
url: '/api/save',
method: 'post',
data: params, // params 的内容会作为 JSON Body 发送
});
}
关键点:函数入参名叫 data 还是 params 不重要,真正决定参数位置的是 request 配置对象的 params 和 data 字段。
Axios 混合使用示例
js
axios.post('/api/users',
{ name: 'Alice' }, // 这是 data,放请求体
{ params: { page: 1 } } // 这是 params,拼 URL
)
实际发出的请求:
http
POST /api/users?page=1
Content-Type: application/json
{
"name": "Alice"
}
三、底层原理
第一层:HTTP 协议层
一个 POST 请求由三部分组成:
http
POST /api/print?id=1 HTTP/1.1
Content-Type: application/json
{
"skuCode": "A001"
}
?id=1是 URL 查询参数(由 Axiosparams控制){ "skuCode": "A001" }是请求体 Body(由 Axiosdata控制)- HTTP 协议允许二者同时存在
第二层:Axios 内部处理
Axios 内部对 params 和 data 走两条不同的处理流水线:
js
// params -> 拼接到 URL
url = buildURL(url, params, paramsSerializer)
// 结果:/api/xxx?page=1&size=10
// data -> 放进请求体
if (typeof data === 'object') {
data = JSON.stringify(data)
headers['Content-Type'] = 'application/json'
}
xhr.send(data)
params经过buildURL+paramsSerializer变成?key=valuedata经过transformRequest变成 JSON / FormData / URLSearchParams,再交给xhr.send()
第三层:浏览器底层
Axios 最终调用的是浏览器的 XMLHttpRequest 或 Fetch API:
js
const xhr = new XMLHttpRequest()
xhr.open('POST', url) // url 已包含 params 拼接的 ?key=value
xhr.send(body) // body 就是 data 处理后的结果
本质总结:
params -> 影响 URL(xhr.open 的第二个参数)
data -> 影响 Body(xhr.send 的参数)
四、data 的自动序列化机制(transformRequest)
data 不是简单的原样发送,Axios 内部有 transformRequest 处理链:
| data 类型 | 处理方式 | 默认 Content-Type |
|---|---|---|
普通对象 {} |
JSON.stringify() |
application/json |
FormData |
原样传递 | multipart/form-data(浏览器自动设置 boundary) |
URLSearchParams |
转为 key=value&... |
application/x-www-form-urlencoded |
string |
原样传递 | text/plain |
ArrayBuffer |
原样传递 | 由调用方指定 |
五、后端如何对应
| 后端框架 | 接收 params | 接收 data |
|---|---|---|
| Spring Boot | @RequestParam / getParameter() |
@RequestBody |
| Express.js | req.query |
req.body |
| Django | request.GET |
request.POST / json.loads(request.body) |
| Go | r.URL.Query() |
json.NewDecoder(r.Body) |
六、最佳实践
- 看接口文档选择 :文档写
@RequestParam用params;写@RequestBody用data - POST 请求优先用
data:绝大多数 POST 接口是提交业务数据,参数应放在请求体 params适合"路由/过滤"语义 :分页page/size、状态status=active、ID 等简单标识data适合"提交/创建"语义:表单数据、对象创建、批量操作- 二者可以共存 :如
params传分页参数,data传查询条件
七、常见踩坑
坑 1:POST + params 后端收不到数据
ts
// 错误:后端用 @RequestBody 接收,但参数被拼到了 URL
request({ url: '/api/save', method: 'post', params: { name: 'test' } })
// 正确:参数应放请求体
request({ url: '/api/save', method: 'post', data: { name: 'test' } })
坑 2:变量名误导
ts
// 入参叫 data,但实际走的是 params(拼 URL),容易误判
function api(data) { return request({ url: '...', params: data }) }
建议 :保持命名一致性------走 params 时入参命名为 query 或 queryParams;走 data 时命名为 body 或 payload。