日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Vue中Axios的封裝和API接口的管理

 如圖,面對一團糟代碼的你~~~真的想說,What F~U~C~K?。。?/p>

專注于為中小企業(yè)提供成都網(wǎng)站建設、網(wǎng)站設計服務,電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)達孜免費做網(wǎng)站提供優(yōu)質的服務。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了成百上千企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設實現(xiàn)規(guī)模擴充和轉變。

回歸正題,我們所要的說的axios的封裝和api接口的統(tǒng)一管理,其實主要目的就是在幫助我們簡化代碼和利于后期的更新維護。

一、axios的封裝

在vue項目中,和后臺交互獲取數(shù)據(jù)這塊,我們通常使用的是axios庫,它是基于promise的http庫,可運行在瀏覽器端和node.js中。他有很多優(yōu)秀的特性,例如攔截請求和響應、取消請求、轉換json、客戶端防御XSRF等。所以我們的尤大大也是果斷放棄了對其官方庫vue-resource的維護,直接推薦我們使用axios庫。如果還對axios不了解的,可以移步axios文檔。

安裝 

 
 
 
 
  1. npm install axios; // 安裝axios 

引入

一般我會在項目的src目錄中,新建一個request文件夾,然后在里面新建一個http.js和一個api.js文件。http.js文件用來封裝我們的axios,api.js用來統(tǒng)一管理我們的接口。 

 
 
 
 
  1. // 在http.js中引入axios  
  2. import axios from 'axios'; // 引入axios  
  3. import QS from 'qs'; // 引入qs模塊,用來序列化post類型的數(shù)據(jù),后面會提到  
  4. // vant的toast提示框組件,大家可根據(jù)自己的ui組件更改。  
  5. import { Toast } from 'vant';  

環(huán)境的切換

我們的項目環(huán)境可能有開發(fā)環(huán)境、測試環(huán)境和生產(chǎn)環(huán)境。我們通過node的環(huán)境變量來匹配我們的默認的接口url前綴。axios.defaults.baseURL可以設置axios的默認請求地址就不多說了。 

 
 
 
 
  1. // 環(huán)境的切換  
  2. if (process.env.NODE_ENV == 'development') {      
  3.     axios.defaults.baseURL = 'https://www.baidu.com';}   
  4. else if (process.env.NODE_ENV == 'debug') {      
  5.     axios.defaults.baseURL = 'https://www.ceshi.com';  
  6. }   
  7. else if (process.env.NODE_ENV == 'production') {      
  8.     axios.defaults.baseURL = 'https://www.production.com';  

設置請求超時

通過axios.defaults.timeout設置默認的請求超時時間。例如超過了10s,就會告知用戶當前請求超時,請刷新等。 

 
 
 
 
  1. axios.defaults.timeout = 10000; 

post請求頭的設置

post請求的時候,我們需要加上一個請求頭,所以可以在這里進行一個默認的設置,即設置post的請求頭為application/x-www-form-urlencoded;charset=UTF-8 

 
 
 
 
  1. axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; 
  •  請求攔截

我們在發(fā)送請求前可以進行一個請求的攔截,為什么要攔截呢,我們攔截請求是用來做什么的呢?比如,有些請求是需要用戶登錄之后才能訪問的,或者post請求的時候,我們需要序列化我們提交的數(shù)據(jù)。這時候,我們可以在請求被發(fā)送之前進行一個攔截,從而進行我們想要的操作。

請求攔截 

 
 
 
 
  1. // 先導入vuex,因為我們要使用到里面的狀態(tài)對象  
  2. // vuex的路徑根據(jù)自己的路徑去寫  
  3. import store from '@/store/index';  
  4. // 請求攔截器axios.interceptors.request.use(     
  5.     config => {          
  6.         // 每次發(fā)送請求之前判斷vuex中是否存在token      
  7.          // 如果存在,則統(tǒng)一在http請求的header都加上token,這樣后臺根據(jù)token判斷你的登錄情況  
  8.         // 即使本地存在token,也有可能token是過期的,所以在響應攔截器中要對返回狀態(tài)進行判斷   
  9.         const token = store.state.token;          
  10.         token && (config.headers.Authorization = token);       
  11.          return config;   
  12.      },      
  13.     error => {          
  14.         return Promise.error(error);    
  15.  }) 

這里說一下token,一般是在登錄完成之后,將用戶的token通過localStorage或者cookie存在本地,然后用戶每次在進入頁面的時候(即在main.js中),會首先從本地存儲中讀取token,如果token存在說明用戶已經(jīng)登陸過,則更新vuex中的token狀態(tài)。然后,在每次請求接口的時候,都會在請求的header中攜帶token,后臺人員就可以根據(jù)你攜帶的token來判斷你的登錄是否過期,如果沒有攜帶,則說明沒有登錄過。這時候或許有些小伙伴會有疑問了,就是每個請求都攜帶token,那么要是一個頁面不需要用戶登錄就可以訪問的怎么辦呢?其實,你前端的請求可以攜帶token,但是后臺可以選擇不接收啊!

響應的攔截 

 
 
 
 
  1. // 響應攔截器  
  2. axios.interceptors.response.use(      
  3.     response => {     
  4.         // 如果返回的狀態(tài)碼為200,說明接口請求成功,可以正常拿到數(shù)據(jù)    
  5.          // 否則的話拋出錯誤  
  6.         if (response.status === 200) {           
  7.              return Promise.resolve(response);    
  8.         } else {              
  9.             return Promise.reject(response);        
  10.          }      
  11.     },      
  12.     // 服務器狀態(tài)碼不是2開頭的的情況  
  13.     // 這里可以跟你們的后臺開發(fā)人員協(xié)商好統(tǒng)一的錯誤狀態(tài)碼    
  14.      // 然后根據(jù)返回的狀態(tài)碼進行一些操作,例如登錄過期提示,錯誤提示等等  
  15.     // 下面列舉幾個常見的操作,其他需求可自行擴展  
  16.     error => {              
  17.         if (error.response.status) {              
  18.             switch (error.response.status) {                
  19.                  // 401: 未登錄  
  20.                 // 未登錄則跳轉登錄頁面,并攜帶當前頁面的路徑  
  21.                 // 在登錄成功后返回當前頁面,這一步需要在登錄頁操作。                
  22.                  case 401:                      
  23.                     router.replace({                          
  24.                         path: '/login',                        
  25.                          query: {   
  26.                             redirect: router.currentRoute.fullPath   
  27.                         }  
  28.                     });  
  29.                     break; 
  30.                  // 403 token過期  
  31.                 // 登錄過期對用戶進行提示  
  32.                 // 清除本地token和清空vuex中token對象  
  33.                 // 跳轉登錄頁面                  
  34.                 case 403:  
  35.                      Toast({  
  36.                         message: '登錄過期,請重新登錄',  
  37.                         duration: 1000,  
  38.                         forbidClick: true  
  39.                     });  
  40.                     // 清除token  
  41.                     localStorage.removeItem('token');  
  42.                     store.commit('loginSuccess', null);  
  43.                     // 跳轉登錄頁面,并將要瀏覽的頁面fullPath傳過去,登錄成功后跳轉需要訪問的頁面   
  44.                     setTimeout(() => {                        
  45.                          router.replace({                            
  46.                              path: '/login',                            
  47.                              query: {   
  48.                                 redirect: router.currentRoute.fullPath   
  49.                             }                          
  50.                         });                      
  51.                     }, 1000);                      
  52.                     break;   
  53.                 // 404請求不存在  
  54.                 case 404:  
  55.                     Toast({  
  56.                         message: '網(wǎng)絡請求不存在',  
  57.                         duration: 1500,  
  58.                         forbidClick: true  
  59.                     });  
  60.                     break;  
  61.                 // 其他錯誤,直接拋出錯誤提示  
  62.                 default:  
  63.                     Toast({  
  64.                         message: error.response.data.message,  
  65.                         duration: 1500,  
  66.                         forbidClick: true  
  67.                     });  
  68.             }  
  69.             return Promise.reject(error.response);  
  70.         } 
  71.      }      
  72. }); 

響應攔截器很好理解,就是服務器返回給我們的數(shù)據(jù),我們在拿到之前可以對他進行一些處理。例如上面的思想:如果后臺返回的狀態(tài)碼是200,則正常返回數(shù)據(jù),否則的根據(jù)錯誤的狀態(tài)碼類型進行一些我們需要的錯誤,其實這里主要就是進行了錯誤的統(tǒng)一處理和沒登錄或登錄過期后調整登錄頁的一個操作。

要注意的是,上面的Toast()方法,是我引入的vant庫中的toast輕提示組件,你根據(jù)你的ui庫,對應使用你的一個提示組件。

封裝get方法和post方法

我們常用的ajax請求方法有get、post、put等方法,相信小伙伴都不會陌生。axios對應的也有很多類似的方法,不清楚的可以看下文檔。但是為了簡化我們的代碼,我們還是要對其進行一個簡單的封裝。下面我們主要封裝兩個方法:get和post。

get方法:我們通過定義一個get函數(shù),get函數(shù)有兩個參數(shù),第一個參數(shù)表示我們要請求的url地址,第二個參數(shù)是我們要攜帶的請求參數(shù)。get函數(shù)返回一個promise對象,當axios其請求成功時resolve服務器返回 值,請求失敗時reject錯誤值。最后通過export拋出get函數(shù)。 

 
 
 
 
  1. /**  
  2.  * get方法,對應get請求  
  3.  * @param {String} url [請求的url地址]  
  4.  * @param {Object} params [請求時攜帶的參數(shù)]  
  5.  */  
  6. export function get(url, params){      
  7.     return new Promise((resolve, reject) =>{        
  8.          axios.get(url, {              
  9.             params: params          
  10.         }).then(res => {  
  11.             resolve(res.data);  
  12.         }).catch(err =>{  
  13.             reject(err.data)        
  14.      })     
  15.  });} 

**post方法:**原理同get基本一樣,但是要注意的是,post方法必須要使用對提交從參數(shù)對象進行序列化的操作,所以這里我們通過node的qs模塊來序列化我們的參數(shù)。這個很重要,如果沒有序列化操作,后臺是拿不到你提交的數(shù)據(jù)的。這就是文章開頭我們import QS from 'qs';的原因。如果不明白序列化是什么意思的,就百度一下吧,答案一大堆。 

 
 
 
 
  1. /**   
  2.  * post方法,對應post請求  
  3.  * @param {String} url [請求的url地址]   
  4.  * @param {Object} params [請求時攜帶的參數(shù)]   
  5.  */  
  6. export function post(url, params) {  
  7.     return new Promise((resolve, reject) => {  
  8.          axios.post(url, QS.stringify(params))  
  9.         .then(res => {  
  10.             resolve(res.data);  
  11.         })  
  12.         .catch(err =>{  
  13.             reject(err.data)  
  14.         })  
  15.     });  

這里有個小細節(jié)說下,axios.get()方法和axios.post()在提交數(shù)據(jù)時參數(shù)的書寫方式還是有區(qū)別的。區(qū)別就是,get的第二個參數(shù)是一個{},然后這個對象的params屬性值是一個參數(shù)對象的。而post的第二個參數(shù)就是一個參數(shù)對象。兩者略微的區(qū)別要留意哦!

axios的封裝基本就完成了,下面再簡單說下api的統(tǒng)一管理。

整齊的api就像電路板一樣,即使再復雜也能很清晰整個線路。上面說了,我們會新建一個api.js,然后在這個文件中存放我們所有的api接口。

  •  首先我們在api.js中引入我們封裝的get和post方法 
 
 
 
 
  1. /**     
  2.  * api接口統(tǒng)一管理  
  3.  */  
  4. import { get, post } from './http' 

現(xiàn)在,例如我們有這樣一個接口,是一個post請求: 

 
 
 
 
  1. http://www.baiodu.com/api/v1/users/my_address/address_edit_before 

我們可以在api.js中這樣封裝: 

 
 
 
 
  1. export const apiAddress = p => post('api/v1/users/my_address/address_edit_before', p); 

我們定義了一個apiAddress方法,這個方法有一個參數(shù)p,p是我們請求接口時攜帶的參數(shù)對象。而后調用了我們封裝的post方法,post方法的第一個參數(shù)是我們的接口地址,第二個參數(shù)是apiAddress的p參數(shù),即請求接口時攜帶的參數(shù)對象。最后通過export導出apiAddress。

然后在我們的頁面中可以這樣調用我們的api接口: 

 
 
 
 
  1. import { apiAddress } from '@/request/api';// 導入我們的api接口  
  2. export default {      
  3.      name: 'Address',   
  4.      created () {  
  5.         this.onLoad();  
  6.     },  
  7.     methods: {             
  8.         // 獲取數(shù)據(jù)            
  9.          onLoad() {  
  10.             // 調用api接口,并且提供了兩個參數(shù)                
  11.              apiAddress({                     
  12.                  type: 0,                    
  13.                  sort: 1                
  14.              }).then(res => { 
  15.                  // 獲取數(shù)據(jù)成功后的其他操作  
  16.                 ………………                
  17.              })             
  18.          }          
  19.     }  

其他的api接口,就在pai.js中繼續(xù)往下面擴展就可以了。友情提示,為每個接口寫好注釋哦?。。?/p>

api接口管理的一個好處就是,我們把api統(tǒng)一集中起來,如果后期需要修改接口,我們就直接在api.js中找到對應的修改就好了,而不用去每一個頁面查找我們的接口然后再修改會很麻煩。關鍵是,萬一修改的量比較大,就規(guī)格gg了。還有就是如果直接在我們的業(yè)務代碼修改接口,一不小心還容易動到我們的業(yè)務代碼造成不必要的麻煩。

好了,最后把完成的axios封裝代碼奉上。 

 
 
 
 
  1. /**axios封裝  
  2.  * 請求攔截、相應攔截、錯誤統(tǒng)一處理  
  3.  */  
  4. import axios from 'axios';import QS from 'qs';  
  5. import { Toast } from 'vant';  
  6. import store from '../store/index'  
  7. // 環(huán)境的切換  
  8. if (process.env.NODE_ENV == 'development') {    
  9.      axios.defaults.baseURL = '/api';  
  10. } else if (process.env.NODE_ENV == 'debug') {    
  11.      axios.defaults.baseURL = ''; 
  12.  } else if (process.env.NODE_ENV == 'production') {    
  13.      axios.defaults.baseURL = 'http://api.123dailu.com/'; 
  14.  }  
  15. // 請求超時時間  
  16. axios.defaults.timeout = 10000;  
  17. // post請求頭  
  18. axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';  
  19. // 請求攔截器  
  20. axios.interceptors.request.use(      
  21.     config => {  
  22.         // 每次發(fā)送請求之前判斷是否存在token,如果存在,則統(tǒng)一在http請求的header都加上token,不用每次請求都手動添加了  
  23.         // 即使本地存在token,也有可能token是過期的,所以在響應攔截器中要對返回狀態(tài)進行判斷  
  24.         const token = store.state.token;          
  25.         token && (config.headers.Authorization = token);         
  26.          return config;      
  27.     },      
  28.     error => {         
  29.          return Promise.error(error);     
  30.     })  
  31. // 響應攔截器  
  32. axios.interceptors.response.use(    
  33.      response => {          
  34.         if (response.status === 200) {           
  35.              return Promise.resolve(response);       
  36.          } else {              
  37.             return Promise.reject(response);        
  38.          }      
  39.     },  
  40.     // 服務器狀態(tài)碼不是200的情況   
  41.      error => {          
  42.         if (error.response.status) {            
  43.              switch (error.response.status) {                
  44.                  // 401: 未登錄                  
  45.                 // 未登錄則跳轉登錄頁面,并攜帶當前頁面的路徑               
  46.                  // 在登錄成功后返回當前頁面,這一步需要在登錄頁操作。                
  47.                  case 401:                     
  48.                      router.replace({                        
  49.                          path: '/login',                        
  50.                          query: { redirect: router.currentRoute.fullPath }   
  51.                     });  
  52.                     break;  
  53.                 // 403 token過期                
  54.                  // 登錄過期對用戶進行提示                
  55.                  // 清除本地token和清空vuex中token對象                
  56.                  // 跳轉登錄頁面                
  57.                  case 403:                     
  58.                      Toast({                         
  59.                          message: '登錄過期,請重新登錄',                        
  60.                          duration: 1000,                        
  61.                          forbidClick: true                     
  62.                      });                    
  63.                      // 清除token                    
  64.                      localStorage.removeItem('token');                     
  65.                      store.commit('loginSuccess', null);                     
  66.                      // 跳轉登錄頁面,并將要瀏覽的頁面fullPath傳過去,登錄成功后跳轉需要訪問的頁面 
  67.                      setTimeout(() => {                         
  68.                          router.replace({                             
  69.                              path: '/login',                            
  70.                              query: {   
  71.                                 redirect: router.currentRoute.fullPath   
  72.                             }                        
  73.                          });                     
  74.                      }, 1000);                     
  75.                      break;   
  76.                 // 404請求不存在                
  77.                  case 404:                     
  78.                      Toast({                        
  79.                          message: '網(wǎng)絡請求不存在',                        
  80.                          duration: 1500,                         
  81.                          forbidClick: true                     
  82.                      });                     
  83.                  break;                 
  84.                  // 其他錯誤,直接拋出錯誤提示                 
  85.                  default:                     
  86.                      Toast({                         
  87.                          message: error.response.data.message,                         
  88.                          duration: 1500,                         
  89.                          forbidClick: true                     
  90.                      });            
  91.              }             
  92.              return Promise.reject(error.response);        
  93.          }         
  94.     }  
  95. );  
  96. /**   
  97.  * get方法,對應get請求   
  98.  * @param {String} url [請求的url地址] 
  99.   * @param {Object} params [請求時攜帶的參數(shù)]   
  100.  */  
  101. export function get(url, params){      
  102.     return new Promise((resolve, reject) =>{        
  103.          axios.get(url, {           
  104.              params: params         
  105.          })         
  106.          .then(res => {             
  107.              resolve(res.data);         
  108.          })         
  109.          .catch(err => {             
  110.              reject(err.data)         
  111.          })     
  112.      }); 
  113.  } 
  114.  /**   
  115.  * post方法,對應post請求   
  116.  * @param {String} url [請求的url地址]   
  117.  * @param {Object} params [請求時攜帶的參數(shù)]   
  118.  */  
  119. export function post(url, params) {      
  120.     return new Promise((resolve, reject) => {         
  121.          axios.post(url, QS.stringify(params))       
  122.          .then(res => {              
  123.             resolve(res.data);          
  124.         })         
  125.          .catch(err => {             
  126.              reject(err.data)         
  127.          })     
  128.      }); 
  129.  } 

如果喜歡,就給個吧(*^▽^*)

*********華麗麗的分割線******************華麗麗的分割線******************華麗麗的分割線******************華麗麗的分割線******************華麗麗的分割線*********

2018.8.14更新

axios的封裝根據(jù)需求的不同而不同。這里非常感謝評論里一些很中肯的建議,我也對此進行了思考和針對不同需求的改善。主要有以下改變:

1.優(yōu)化axios封裝,去掉之前的get和post

2.斷網(wǎng)情況處理

3.更加模塊化的api管理

4.接口域名有多個的情況

5.api掛載到vue.prototype上省去引入的步驟

http.js中axios封裝的優(yōu)化,先直接貼代碼: 

 
 
 
 
  1. /**  
  2.  * axios封裝  
  3.  * 請求攔截、響應攔截、錯誤統(tǒng)一處理  
  4.  */  
  5. import axios from 'axios';  
  6. import router from '../router';  
  7. import store from '../store/index';  
  8. import { Toast } from 'vant';  
  9. /**   
  10.  * 提示函數(shù)   
  11.  * 禁止點擊蒙層、顯示一秒后關閉  
  12.  */  
  13. const tip = msg => {      

  14. 分享題目:Vue中Axios的封裝和API接口的管理
    網(wǎng)站網(wǎng)址:http://m.5511xx.com/article/cophgpe.html