因为在很多项目中很多组件都需要通过 Axios 发送异步请求,所以封装一个 Axios 对象,自己封装的 Axios 在后续可以使用 axios 中提供的拦截器。
安装
npm install axios
1、 首先在项目 src 文件夹下创建 utils 目录,在其下创建 request.js 文件。
具体怎么封装,可以看一下这个文档:
https://github.com/axios/axios#creating-an-instance
2、在 request.js 文件中引入 axios ,并且创建一个 axios 对象。
// 首先导入 axios
import axios from 'axios'
// 自己创建一个axios对象
const request = axios.create({
baseURL: '/', // 基础路径,默认是/ ,如果改了,会自动添加到你请求url前面
timeout: 5000 // 请求超时,5000毫秒
})
然后导出自定义创建的axios对象。
export default request // 导出自定义创建的 axios 对象
3、还可以在里面定义拦截器。
// 请求拦截器
request.interceptors.request.use( config => {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 处理请求错误
return Promise.reject(error);
});
// 相应拦截器
request.interceptors.response.use( response => {
// 在2xx范围内的任何状态代码都会触发此功能
// 处理响应数据
return response;
}, function (error) {
// 任何超出2xx范围的状态代码都会触发此功能
// 处理响应错误
return Promise.reject(error);
});
到此为止 request.js 整体代码:
// 首先导入 axios
import axios from 'axios'
// 自己创建一个axios对象
const request = axios.create({
baseURL: '/', // 基础路径,默认是/ ,如果改了,会自动添加到你请求url前面
timeout: 5000 // 请求超时,5000毫秒
})
// 请求拦截器
request.interceptors.request.use( config => {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 处理请求错误
return Promise.reject(error);
});
// 相应拦截器
request.interceptors.response.use( response => {
// 在2xx范围内的任何状态代码都会触发此功能
// 处理响应数据
return response;
}, function (error) {
// 任何超出2xx范围的状态代码都会触发此功能
// 处理响应错误
return Promise.reject(error);
});
export default request // 导出自定义创建的 axios 对象
我们之前封装了一个自己的 axios 对象,拦截器也写了,尽管没内容,但是你去网上搜,大部分拦截器的功能是一样的,这个都能用,后面有时间在写,现在呢,我们的使用一下上面封装的 axios 对象。
首先我们在项目 src 目录下在创建一个文件夹 api ,以后我们调接口都在 api 目录下调用,在 api 文件夹下创建一个 test.js 文件,然后在 test.js 中发送异步请求。
// 首先引入我们自定义的axios对象
import request from '@/utils/request'
// 创建一个get请求 第一种,不建议使用
// request.get('/db.json').then( rep =>{
// console.log('--->', rep.data)
// })
// 创建一个get请求,第二种,推荐使用
request({
methods: 'get',
url:'/db.json'
}).then( rep =>{
console.log('--->', rep.data)
})
现在我们测试是可以的,但是我们得把这个请求导出,给组件使用,所以把 test.js 修改一下:
// 首先引入我们自定义的axios对象
import request from '@/utils/request'
// 创建一个get请求,第二种,推荐使用
// request({
// methods: 'get',
// url:'/db.json'
// }).then( rep =>{
// console.log('get--->', rep.data)
// })
// 导出对象
export default {
getList(){
// 把请求对象返回,提供给组件使用
const req = request({
methods: 'get',
url: '/db.json'
})
return req
}
}
在组件中使用:
<template>
<div class="hello">
<h1>我最棒</h1>
<p v-for="(item, index) of list" :key="index">{{item.name}}</p>
</div>
</template>
<script>
// 导入
import testApi from "@/api/test";
export default {
name: "HelloWorld",
created() {
this.initData();
},
data(){
return{
list: []
}
},
methods: {
initData() {
// 调用
testApi.getList().then(res =>{
console.log('组件请求返回数据---> ', res.data)
this.list = res.data
})
}
}
};
</script>
<style scoped lang="scss">
</style>
访问采用的是同源策略,是指协议、域名、端口都要相同,其中有一个不同,就会产生跨域问题,浏览器就会限制跨域访问。
跨域问题是前端开发经常遇到的问题,在什么时候会遇到跨域问题呢?首先是前后端分离项目,使用vue开发前端项目了,肯定是前后端分离,我在说一个废话,哈哈哈哈,当前端项目和后端,也就是java后台或者是php后台间,他们的IP地址不一样,或者是端口不一样,这时候就会出现跨域问题。
比如,前后端项目开发完成,尽管部署在同一服务器下,IP地址肯定是一样的,但是端口肯定是不一样的,比如前段端口是8888,后端端口是8001,这时候就存在跨域问题,人家不让你调用,气人不!哈哈哈哈嗝~ 更有甚者,人家前端一个服务器,后端一个服务器,哈哈哈哈哈,恐怖!
解决跨域:
如下配置:
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/db.json 最终会转发到 http://localhost:8001/db.json
'^/dev-api': '', // 就是将请求地址中的 /dev-api 前缀替换成空的
}
}
}
},
lintOnSave: false, // 关闭格式检查
productionSourceMap: false, // 打包时不会生成 .map 文件,加快打包速度
}
再请求的时候加一个前缀 /dev-api
加了前缀之后,加入我们后期要修改前缀,案例就一个接口好修改,但是如果以后成百上千个接口,一个一个改有些许的费劲,所以我们就把前缀抽取出来,修改接口 test.js 文件内容如下:
// 首先引入我们自定义的axios对象
import request from '@/utils/request'
// 将前缀抽取出来,以后改的话就改这个地方就行
const BASE_URI = '/dev-api'
// 导出对象
export default {
getList(){
// 把请求对象返回,提供给组件使用
const req = request({
methods: 'get',
url: BASE_URI + '/db.json' // 拼接前缀
})
return req
}
}
效果是一样的。
如果后期需要修改跨域服务器的地址,就在 在 vue.config.js 文件中使用 devServer.proxy 选项中修改地址就可以了。
配置完跨域需要重启服务,不然不起作用。
OK! 跨域的问题没有了,现在可以夸我啦!!!
参考资料:https://cli.vuejs.org/zh/guide/mode-and-env.html
开发环境请求接口数据和生产环境请求接口数据一般是不同的,配置不同环境的目的就是因为接口的不同不至于整天批量改URL。所以为不同的环境配置不同的请求接口 URL,通过路径前的前缀进行匹配,当前只针对的是开发环境,以后如果有生产再说哈。
在项目根目录下创建一个文件,名字叫做 .env.development, 将开发环境的配置项配置到此文件中。
在此文件中配置的各个配置项,都只能在开发环境中使用。
如果在根目录下再创建一个 .env.production 文件,那么在这个文件中所有的配置项,只能在生产环境下使用。
注意名字千万别敲错了哈,不然不管用。
那什么样的参数/变量一般需要配置呢? 首先,代理服务器的地址需要可配置,其次代理前缀需要可配置,因为代理服务器生产环境和测试环境肯定不同,而前缀也可能因为服务器的不同而有所改变。
首先在 .env.development 文件写入配置项
# 只有以 VUE_APP_ 开头的变量会被 webpack 静态嵌入到客户端侧的包中进行使用 process.env.VUE_APP_xxx。
# 目标服务接口地址,这个地址按照自己服务环境来的,添加修改后需要重启服务
VUE_APP_HT_URL = 'http://localhost:8001'
# 开发环境前缀
VUE_APP_BASE_API = '/dev-api'
然后修改代理项
module.exports = {
devServer: {
port: 8002, // 端口号,如果端口号被占用,会自动提升1
host: "localhost", //主机名, 127.0.0.1, 真机 0.0.0.0
https: false, //协议
open: true, //启动服务时自动打开浏览器访问
proxy: { // 开发环境代理配置
// '/dev-api': { // 意思是当请求是以 dev-api 开头的请求,都走代理
[process.env.VUE_APP_BASE_API]: {
// 目标服务器地址,代理访问:http://localhost:8001
target: 'http://localhost:8001',
// target: process.env.VUE_APP_HT_URL, // 我改成这种失败了,请求500 大佬知道原因教我!!!
changeOrigin: true, // 开启代理服务器,就会给你代理转发
pathRewrite: {
// /dev-api/db.json 最终会转发到 http://localhost:8001/db.json
// '^/dev-api': '', // 就是将请求地址中的 /dev-api 前缀替换成空的
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
}
},
lintOnSave: false, // 关闭格式检查
productionSourceMap: false, // 打包时不会生成 .map 文件,加快打包速度
}
之前我们在请求的时候在 test.js 文件中加了一个 BASE_URI = ‘/dev-api’ ,现在我们可以简化一下,因为在 request.js 文件创建 axios 对象的时候,有一个 baseURL ,当时我们设置的是 ‘/’ ,我们可以直接设置成 ‘/dev-api’,test.js 中就不需要设置前缀了,记得把前缀删掉!
// 自己创建一个axios对象
const request = axios.create({
baseURL: '/dev-api', // 基础路径,默认是/ ,如果改了,会自动添加到你请求url前面
timeout: 5000 // 请求超时,5000毫秒
})
因为之前我们在 .env.development 文件定义了一个前缀,所以还可以这样改
// 自己创建一个axios对象
const request = axios.create({
// baseURL: '/dev-api', // 基础路径,默认是/ ,如果改了,会自动添加到你请求url前面
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000 // 请求超时,5000毫秒
})
效果是一样的,需要修改的时候也不需要再去找文件,直接在 .env.development 文件统一修改就可以了。
【相关代码:https://gitee.com/wjw1014/vue_learning_axios】