【Vue3速成】08-vue3异步请求之Axios-02

📅 2026/8/6 11:56:31
【Vue3速成】08-vue3异步请求之Axios-02
你正在阅读「半路出家玩前端」系列文章 弹简特 个人主页❄️个人专栏直通车接口测试从入门到跑路☕一个后端的 JavaEE 续命指南网络原理续命手册☕Java项目-轻聊☕Java项目-企悦抽✨靠热爱去书写自己靠勇敢去书写生活 博主简介:文章目录一、前言二、 第一步用 axios.get / axios.post 简写请求1、这步做什么2、代码长什么样2.1 GET2.2 POST3、写了立刻多了什么4、此刻数据 / 结构怎么变三、跨域是什么、怎么解1、这步做什么2、失败时控制台 / 网络里能看到啥3、方案 A后端加注解4、方案 B前端 Vite 代理开发环境常用4.1 这步做什么4.2 代码vite.config.js4.3 写了立刻多了什么4.4 代理路径上数据怎么变5、预检请求 OPTIONS四、拦截器 —— 所有请求进出都过一道门1、这步做什么2、为什么要单独建 request.js3、封装代码4、 拦截过程中数据长什么样4.1 和路由守卫的区别5、导入命名别把自己绕晕五、串起来推荐书写顺序架构一、前言上一期我们大致了解了axios的相关知识之后本期我们补充一下axios的get/post以及拦截器等等知识二、 第一步用 axios.get / axios.post 简写请求1、这步做什么以前常写axios({method:get,url:...,params:{...}})现在改成更短的axios.get / axios.post类似后端四种映射的简化版。以后真正开发多数直接点方法名而不是每次手写method。2、代码长什么样2.1 GET// 语法axios.get(url[, config])// 第二个参数是「配置」params、headers 等都放这里GET 没有单独的「请求体参数位」returnaxios.get(http://localhost:8080/api/qinghua,{params:{// 会拼到 URL 后面?formatjsonformat:json,},headers:{// 自定义头后端可用 RequestHeader(token) 取token:a.bb.cc,Accept:application/json,},})2.2 POST// 语法axios.post(url[, data[, config]])// 第二个参数 请求体 JSON整段对象直接传不要再包一层 data:// 第三个参数 配置params / headersreturnaxios.post(http://localhost:8080/api/login,{// ↓ 这整段就是请求体username:zhangsan,password:123456,},{params:{age:18},// 仍可走 URL 问号参数headers:{token:a.bb.cc},// 请求头})3、写了立刻多了什么写法你省掉了什么返回值仍然是axios.get不用写method:getPromiseaxios.post不用写method:postbody 位置固定Promise配合async/await时return axios.get(...)返回的仍是 Promise外面await就能等结果。4、此刻数据 / 结构怎么变T0 你调用 axios.get(url, config) 内存里准备好url 字符串 config 对象堆上 T1 Axios 组装真实 HTTP 请求 URL url ?params键值对 Header config.headers Body GET 通常为空 T2 换成 axios.post(url, bodyObj, config) URL url ?params Header config.headers Body JSON.stringify(bodyObj) ← 第二参数整段进请求体 T3 后端按「位置」取值别混 URL 参数 → RequestParam 请求体 JSON → RequestBody 请求头 token → RequestHeader三、跨域是什么、怎么解1、这步做什么当前页http://localhost:5173去请求http://localhost:8080/api/qinghua——端口不同就是跨域。浏览器会看目标服务器有没有授权没授权就拦下。一句话定义当前网址和目标网址只要协议 / IP / 端口有一个不一致就算跨域。生活类比小孩在本游乐园里玩没问题突然要去隔壁游乐园必须隔壁同意授权家长浏览器才放行。2、失败时控制台 / 网络里能看到啥常见提示blocked by CORS policy Access-Control-Allow-Origin 头缺失 Axios ERR_NETWORK含义8080 那台服务器没有给你允许跨域的响应头浏览器直接拦住前端进catch。关键响应头服务器授予权限时会出现头例子含义Access-Control-Allow-Origin*或具体源允许哪些来源Access-Control-Allow-MethodsGET,POST允许哪些方法Access-Control-Allow-Headerstoken,...允许哪些自定义头3、方案 A后端加注解CrossOrigin// 可加在类或方法上还可配 origins、methods、allowedHeadersRestControllerpublicclassXxxController{}立刻效果响应里带上允许跨域的头浏览器放行。注意每个 Controller 都加会重复后期微服务常用网关统一处理。4、方案 B前端 Vite 代理开发环境常用4.1 这步做什么让浏览器以为自己只访问「同源」的/api/...由 Vite 开发服务器偷偷转到8080。4.2 代码vite.config.jsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueexportdefaultdefineConfig({plugins:[vue()],server:{proxy:{// 只代理以 /api 开头的请求不要写成 /否则整站静态资源也会被转到后端 → 页面 404/api:{target:http://localhost:8080,// 后端根地址changeOrigin:true,// 修改请求头里的 Host贴近真实转发},},},})前端请求改成相对路径不要再写死http://localhost:8080// 浏览器发出http://localhost:5173/api/qinghua 同源不触发浏览器 CORS// Vite 转发到http://localhost:8080/api/qinghuaawaitaxios.get(/api/qinghua)4.3 写了立刻多了什么浏览器侧不再报 CORS开发期真实流量仍打到 80804.4 代理路径上数据怎么变T0 页面在 5173加载 JS / 静态资源路径不是 /api→ 不走代理 T1 业务代码执行axios.get(/api/qinghua) 浏览器视角目标仍是 5173 同源 T2 Vite 匹配到前缀 /api 拼出target 原路径 → http://localhost:8080/api/qinghua changeOrigin: true → Host 头按目标改写 T3 后端返回 JSON T4 代理把响应原样交回浏览器 → 你的 then / await 收到数据踩坑proxy配成/时访问首页也会被转到后端前端页面打不开。必须用/api这类业务前缀。5、预检请求 OPTIONS非简单跨域请求前浏览器可能先发OPTIONS问一句「让不让」——这叫预检不是业务请求。T1 OPTIONS 预检 → 服务器回 Access-Control-Allow-* T2 若设置了 Max-Age例如 3600 秒→ 有效期内不再重复预检 T3 发送真正的 GET/POST T4 超时或头变化 → 再预检一次有效期内可以直接发正式请求过期或权限头变了要重新问。四、拦截器 —— 所有请求进出都过一道门1、这步做什么给 Axios 加两道关卡关卡API时机请求拦截interceptors.request.use发出去之前响应拦截interceptors.response.use回来之后、业务 then 之前两道关都是use(成功回调, 失败回调)。两种错误别混类型典型原因请求错误网络挂了、后端没启动、请求根本没到服务器响应错误到了服务器但返回 500 等异常状态2、为什么要单独建request.js拦截器要作用在所有请求上属于公共设施。最佳实践src/request.js或axios.js/http.js里axios.create 挂拦截器再export default实例全项目 import 这一个。3、封装代码// src/request.jsimportaxiosfromaxios// ① 创建实例以后都用 instance而不是裸 axiosconstinstanceaxios.create({baseURL:/api,// 子路径前自动加此前缀配合 Vite 代理很合适timeout:10000,// 最长等 10 秒超时前端不再傻等})// ② 请求拦截发出前改 config必须 return configinstance.interceptors.request.use((config){// 两种写法等价config.headers.tokena.bb.cc// config.headers[token] a.bb.cc// 登录后常见做法从本地/Pinia 取真实 token 再挂头returnconfig// 不 return请求发不出去},(error){// 请求还没到达服务器就失败了returnPromise.reject(error)})// ③ 响应拦截成功时直接抽出业务数据instance.interceptors.response.use((response){// 这里帮调用方剥掉一层以后 await 到的就是 data不是完整 responsereturnresponse.data},(error){// 服务器异常等returnPromise.reject(error)})exportdefaultinstancevite.config.js代理保持 §2.4baseURL: /api时业务里写importrequestfrom./request.js// 实际路径/api /qinghua → /api/qinghua → 代理到 8080constdataawaitrequest.get(/qinghua)// 注意因响应拦截已 return response.data这里的 data 已是业务 JSONObject.assign(jsonData,data)4、 拦截过程中数据长什么样T0 业务调用request.get(/qinghua) 传入的是「相对 url」字符串 T1 【请求拦截】入参 config 对象堆上 典型字段url、method、baseURL、headers、timeout、params、data… 你执行headers.token a.bb.cc 必须return config → 此刻结构config 多了一个 token 头其它字段仍在 T2 真实发出 HTTP 完整 URL ≈ baseURL url 再经 Vite 代理到 8080 T3 【响应拦截·成功】入参 response 对象 { data: { code, content }, ← 后端 JSON status: 200, headers: {...}, config: {...}, ... } 你执行return response.data → 传给后面的值从「大 response」变成「小 JSON」 T4 业务里 const back await request.get(...) back 的形态 { code, content } ← 不再是 response 因此不要再写 back.data除非后端又包了一层 Result T5 Object.assign(jsonData, back) 页面模型字段更新 → 视图刷新4.1 和路由守卫的区别响应/请求拦截路由守卫拦什么打后端的 HTTP前端页面跳转生命周期网络请求路由切换典型用途统一加 token、统一拆 data、全局错误登录权限、跳转日志5、导入命名别把自己绕晕// request.js 里export default instanceimportrequestfrom./request.js// 名字可自定importhttpfrom./request.js// 也可以// 建议项目内统一叫 request 或 http避免「导出叫 instance、导入叫 axios」难读团队项目里这份封装文件通常已有人写好日常主要改「挂什么头」。五、串起来推荐书写顺序架构① vite.config.js 配 /api → 8080 代理 ② src/request.js create 请求/响应拦截 export ③ 页面里 import request用 get/post 简写 ④ await 得到的已是业务 data → Object.assign 进 reactive ⑤ 后端接口 可选CrossOrigin有代理时开发期也可不靠注解最小页面调用示例scriptsetupimport{reactive,onMounted}fromvueimportrequestfrom./request.js// 带拦截器的实例constjsonDatareactive({code:0,content:})asyncfunctionload(){try{// get 简写返回值已被响应拦截剥成 dataconstdataawaitrequest.get(/qinghua,{headers:{Accept:application/json},})Object.assign(jsonData,data)}catch(e){console.error(e)}}onMounted(load)/scripttemplatep{{ jsonData.content }}/pbuttonclickload再来一句/button/template