Vue--封装axios跨域
Posted 邹邹很busy。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue--封装axios跨域相关的知识,希望对你有一定的参考价值。
封装axios
因为项目中很多组件中要通过Axios发送异步请求,所以封装一个Axios对象。自己封装的Axios在后续可以使用axios中提供的拦截器。
在src下创建一个utils目录,在utils目录下创建一个request.js文件
在public下创建一个db.json文件,写点数据,用来我们测试
之前我们使用axios发送请求的时候是使用的下面的方式
[ { "name":"张三", "age":17 }, { "name":"李四", "age":52 }, { "name":"王五", "age":37 } ]
import axios from \'axios\' axios.get(\'./db.json\').then(response =>{ console.log(response.data) })
在components下的HelloWorld.vue中引用测试一下
在浏览器 的控制台就可以看到db.json里的数据,这种方法是我们之前的方法,现在我们要封装。
修改request.js文件
import axios from \'axios\' const request = axios.create({ baseURL: \'/\', //基础路径,根据不同环境设置 baseURL, 最终发送请求时的URL为: baseURL + 发送请求时写URL , timeout: 5000 //超时时间,5000毫秒 }) export default request // 导出自定义的axios对象
我们自己封装好了axios,那怎么测试知道我们封装的有没有问题,我们来进行测试
在src目录下创建一个api目录,在下面创建一个test.js文件
在test.js文件里写入如下代码
// @就是src目录的路径 import request from \'@/utils/request\' // 下面的这种是使用最原始的方式来发送get请求 // request.get(\'/db.json\').then(response =>{ // console.log(response.data) // }) // 以对象配置的方式进行指定请求方式 // request({ // method: \'get\', // url: \'/db.json\' // }).then(response =>{ // console.log(\'对象方式\', response.data) // }) export default { getList(){ const res = request({ method: \'get\', url: \'/db.json\' }) return res } }
在HelloWorld.vue的script标签里写如下代码
<script> // 导入接口 import testApi from \'@/api/test\' export default{ data(){ return{ list: {} } }, created(){ // 调用method里的fetchData方法 this.fetchData() }, methods: { fetchData(){ testApi.getList().then(response =>{ console.log(\'get3\',response.data) this.list = response.data // 给data里的list重新赋值 }) } } } // export default { // name: "HelloWorld", // props: { // msg: String // } // }; </script>
刷新浏览器,控制台里可以看到db.json里的数据,则我们的配置是没有问题的。
跨域
前后端分离时,前端和后端API服务器可能不在同一台主机上,就存在跨域问题,浏览器限制了跨域访问。
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域。
如下面示例存在跨域:
前端页面部署在:http://localhost:8001 即本地ip端口8001上;
后端API部署在: http://localhost:8002 即本地ip端口8002上 ;
它们IP一样,但是端口不一样,所以存在跨域问题。
演示跨域:
1.将 zz-mms\\db.json 拷贝到 axios-demo\\public\\ 目录下,axios-demo 工程就是 复制了zz-mms 重命名了
2.axios-demo\\vue-config.js 更改 端口号, 将端口号更改为 8001
3. 启动 axios-demo
npm run serve
启动后,查看控制台显示的访问地址,我的是 http://localhost:8001/
4. 查询是否可以直接访问到数据, 访问 http://localhost:8001/db.json
5. 修改 zz-mms\\src\\api\\test.js , 发送请求给 8001 接口,修改下 BASE_URL 值
const BASE_URL = \'http://localhost:8001\'
6. 重新刷新 页面, 查看控制台报错, 出现跨域问题.
跨域解决:
通过代理请求的方式解决,将 API 请求通过代理服务器请求到 API 服务器。
开发环境中,在 vue.config.js 文件中使用 devServer.proxy 选项进行代理配置。
参考:https://cli.vuejs.org/zh/config/#devserver
解决开发环境跨域问题
在 vue.config.js 文件中使用 devServer.proxy 选项进行代理配置
module.exports = { devServer: { port: 8888, // 端口号,如果端口被占用,会自动加1 host: "localhost", // 主机名,127.0.0.1 真机 0.0.0.0 https: false, // 协议 open: true, // 启动服务时自动打开浏览器访问 proxy: { // 开发环境代理配置 \'dev-api\':{ // 匹配 /dev-api 开头的请求, // 目标服务器地址,代理访问http://localhost:8001 target: \'http://localhost:8001\', changeOrigin: true, // 开启代理服务器 pathRewrite:{ // 会将 /dev-api 替换为 \'\',也就是 /dev-api 会移除, // 如 /dev-api/db.json 代理到 https://localhost:8080/db.json \'^dev-api\': \'\' } } } }, lintOnSave: false, // 关闭格式检查 productionSourceMap: false // 打包时不会生成.map文件,加快打包速度 }
将 test.js 中的 修改如下:
// @就是src目录的路径 import request from \'@/utils/request\' const BASE_URL = \'/dev-api\' export default { getList(){ const res = request({ method: \'get\', url: BASE_URL + \'/db.json\' }) return res } }
重启项目,防止不生效
配置不同环境 常量值
参考:https://cli.vuejs.org/zh/guide/mode-and-env.html
开发环境请求 Mock.js 获取数据,开发环境请求后台接口获取数据,不同环境请求的URL不一样,所以要为不同环境匹配不同请求接口URL,通过路径前缀进行匹配。当前只针对开发环境,后面会生产部署再讲生产如何实现。
1. 在 zz-mms 根目录下创建 .env.development 和 .env.production 文件,
.env.development 文件配置(注意开发和生产环境配置不要搞反了)
VUE_APP_SERVICE_URL 值可更改为你自已配置的 Easy-Mock 接口服务地址
# 使用 VUE_APP_ 开头的变量会被 webpack 自动加载,process.env.VUE_APP_xxx # 开发环境的前缀 VUE_APP_BASE_API = \'/dev-api\' # 目标服务接口地址,是按照自己的环境来的,添加或更改服务后,需要重启服务 VUE_APP_SERVICE_URL = \'http://localhost:8001\'
测试:在 main.js 中添加以下代码,看下浏览器控制台是否会输出
在项目任意模块文件中,都可以使用 process.env.VUE_APP_BASE_API 获取值
console.log(process.env.VUE_APP_BASE_API)
重构代理配置
在重构 vue.config.js 中的 devServer.proxy 代理配置
module.exports = { devServer: { port: 8888, // 端口号,如果端口被占用,会自动加1 host: "localhost", // 主机名,127.0.0.1 真机 0.0.0.0 https: false, // 协议 open: true, // 启动服务时自动打开浏览器访问 proxy: { // 开发环境代理配置
[process.env.VUE_APP_BASE_API]:{ // 自动获取,注意要[],在.env.development里配置的 // 目标服务器地址,在.env.development里配置的。代理访问http://localhost:8001 target: process.env.VUE_APP_SERVICE_URL, changeOrigin: true, // 开启代理服务器 pathRewrite:{ [\'^\' + process.env.VUE_APP_BASE_API]: \'\' // 自动获取 } } } }, lintOnSave: false, // 关闭格式检查 productionSourceMap: false // 打包时不会生成.map文件,加快打包速度 }
修改 utils/request.js 文件配置: baseURL: process.env.VUE_APP_BASE_API
import axios from \'axios\' const request = axios.create({ baseURL: process.env.VUE_APP_BASE_API, //基础路径,.env.development timeout: 5000 //超时时间,5000毫秒 }) // request.get(\'./db.json\').then(response =>{ // 使用request。而不是使用axios // console.log(response.data) // }) export default request // 导出自定义的axios对象
去掉 test.js 中的 BASE_URL
// @就是src目录的路径 import request from \'@/utils/request\' export default { getList(){ const res = request({ method: \'get\', url: \'/db.json\' }) return res } }
重启项目,再次访问
以上是关于Vue--封装axios跨域的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段14——Vue的axios网络请求封装
vue3 + typescript + axios封装(附带loading效果,...并携带跨域处理,...element-plus按需引入)