Vue Axios封裝和跨域問題
封裝 Axios
封裝 Axios 對象
因為在很多項目中很多組件都需要通過 Axios 發送異步請求,所以封裝一個 Axios 對象,自己封裝的 Axios 在后續可以使用 axios 中提供的攔截器。
安裝
npm install axios
1、 首先在項目 src 文件夾下創建 utils 目錄,在其下創建 request.js 文件。

在這個文件里面,我們就導入封裝的 Axios 對象。
具體怎么封裝,可以看一下這個文檔:
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 對象,攔截器也寫了,盡管沒內容,但是你去網上搜,大部分攔截器的功能是一樣的,這個都能用,后面有時間在寫,現在呢,我們的使用一下上面封裝的 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,這時候就存在跨域問題,人家不讓你調用,氣人不!哈哈哈哈嗝~ 更有甚者,人家前端一個服務器,后端一個服務器,哈哈哈哈哈,恐怖!
解決跨域:
- 通過代理請求的方式解決,將 API 請求通過代理服務器請求到 API 服務器。
- 開發環境中,在 vue.config.js 文件中使用 devServer.proxy 選項進行代理配置,參考:https://cli.vuejs.org/zh/config/#devserver
如下配置:
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 文件,那么在這個文件中所有的配置項,只能在生產環境下使用。

注意名字千萬別敲錯了哈,不然不管用。

所以,在配置里面,要以 VUE_APP_ 開頭。
那什么樣的參數/變量一般需要配置呢? 首先,代理服務器的地址需要可配置,其次代理前綴需要可配置,因為代理服務器生產環境和測試環境肯定不同,而前綴也可能因為服務器的不同而有所改變。
首先在 .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】
填坑
上面說我曾經在 .env.development 文件配置了后台連接,在 vue.config.js 文件中調用不到,問題被我老弟找到了,他真是個寶藏男孩,愛死他了。
參考這篇博文:
https://www.cnblogs.com/sese/p/11905402.html
我用的是 cli 4,除了上面的步驟,還有一步很重要的:

配置完成,重啟就可以了!完美!nice!
