前言
我們知道 vue 2.0版本開始推薦使用 axios 來完成前端 ajax 請求,axios 是一個基於Promise 的 http 庫,可以用在瀏覽器和 node.js 中,axios 成為vue全家桶的一個重要部分,對前後端介面請求起著必不可少的作用,本文主要總結一下 axios 的一些小知識點和專案中常見的需要封裝的方法。
正文
1.axios 是什麼?
axios 是一個基於 Promise 的 http 庫,可以用於瀏覽器和 node.js 中,在瀏覽器中建立 XMLHttpRequest 物件(基於ajax的一種封裝),然後呼叫該物件的一些方法實現對後端資料介面的請求,在 node.js 中用於建立 http 請求,支援 Promise Api,可以使用 async/await 語法糖書寫,便於攔截請求和響應,並對請求和響應的資料進行處理,自動轉換 JSON 資料格式,同事用於客戶端支援防禦 XSRF。且目前主流瀏覽器都支援該庫。
常見的安裝方式有以下兩種:
(1)使用 cdn 方式,程式碼中直接引入下面指令碼即可,這種方式適用於小型專案,比如學習的小 demo 等。
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
(2)使用 npm 方式,直接在命令列中新增即可。
npm install axios
2.axios 常見用法?
axios中常用的請求配置如下,只有指定的url是必須項,其他存在預設配置項,method不特殊指定,預設方法為 get 。
{ url: '/user',
// `url` 是用於請求的伺服器 URL method: 'get',
// default `method` 是建立請求時使用的方法 baseURL: 'https://some-domain.com/api/',
// `baseURL` 將自動加在 `url` 前面,除非 `url` 是一個絕對 URL。它可以通過設定一個 `baseURL` 便於為 axios 例項的方法傳遞相對 URL headers: {'X-Requested-With': 'XMLHttpRequest'},
// `headers` 是即將被髮送的自定義請求頭 params: { ID: 12345 },
// 必須是一個無格式物件(plain object)或 URLSearchParams 物件,`params` 是即將與請求一起傳送的 URL 引數 timeout: 1000,
// 如果請求話費了超過 `timeout` 的時間,請求將被中斷,`timeout` 指定請求超時的毫秒數(0 表示無超時時間) withCredentials: false,
// default `withCredentials` 表示跨域請求時是否需要使用憑證 responseType: 'json',
// default `responseType` 表示伺服器響應的資料型別,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream' responseEncoding: 'utf8', // default onUploadProgress: function (progressEvent) {
// `onUploadProgress` 允許為上傳處理進度事件 // Do whatever you want with the native progress event }, onDownloadProgress: function (progressEvent) {
// `onDownloadProgress` 允許為下載處理進度事件 // 對原生進度事件的處理 }, }
(1)get 請求
axios.get('url',{params:{ //這裡是請求引數 }}) .then(res=>{
//這裡是響應後操作 }) .catch(err=>{
//異常捕獲 })
(2)post 請求
axios.post('url',{ name:xxx//引數 },{ headers:xxxx,//請求頭資訊 }) .then(function(res){ //處理成功的函式 相當於success }) .catch(function(error){ //錯誤處理 相當於error })
(3)all、spread 併發請求
axios.all([ axios.get('url'), axios.get('url',{params:{type:'sell',page:1}}) ]) .then(axios.spread((res1,res2)=>{ //返回結果為一個陣列 }))
all()方法入參為一個陣列,陣列元素是每一項請求,回撥函式 .then() 的引數也是一個陣列,裡面的每一項元素表示前面請求的返回結果,使用了 axios.spread作為該回撥函式的引數時,其res1,res2分別代表前面每一項請求的返回結果。
綜上這些方法都只使用於小型專案中,或者學習小 demo 中,在工作開發中遇到處理的請求介面較多,
3.axios 在專案中的常見用法?
(1)小型專案中常見封裝方法,靈活性較高。
首先建立 axios.js 檔案
import originAxios from 'axios' export default function axios(option){ return new Promise((resolve,reject)=>{ //建立axios例項 const instance=originAxios.create({ baseURL:'/api', timeout:5000, headers:'' }); //傳入物件進行網路請求 instance(option) .then(res=>{ resolve(res) }) .catch(err=>{ reject(err) }) }) }
然後在需要傳送請求介面的地方引入
import {axios} from './axios.js' axios({method:"get",url:"url",params:{...}}) .then(res=>{ //請求資料後操作 }) .catch(err=.{ //錯誤處理 })
(2)針對不同請求型別進行二次封裝。
/* *url:請求的url *params:請求的引數 *config:請求時的header資訊 *method:請求方法 */ const request = function ({ url, params, config, method }) { // 如果是get請求 需要拼接引數 let str = ""; if (method === "get" && params) { Object.keys(params).forEach((item) => { str += `${item}=${params[item]}&`; }); } return new Promise((resolve, reject) => { axios[method]( str ? url + "?" + str.substring(0, str.length - 1) : url, params, Object.assign({}, config) ) .then( (response) => { resolve(response.data); }, (err) => { if (err.Cancel) { } else { reject(err); } } ) .catch((err) => { reject(err); }); }); };
具體使用同上。
(3)基於請求響應攔截進行封裝,實際專案開發中常用。
axios 提供的攔截器,用於每次傳送請求和得到響應後進行響應的處理。比如在請求攔截中可以在頁面中新增 loading 動畫,某些請求要求使用者必須登入,判斷使用者是否有token,如果沒有就跳轉到登入頁面等,也可以對請求引數進行序列化操作等 config.data = qs.stringfy(config.params) 等。同樣,響應攔截也可以對響應的資料進行過濾,包括響應失敗的攔截,可以根據響應狀態碼進行不同的操作等。具體方法如下:
首先在工具方法資料夾中建立 request.js 檔案。這裡搭配了token用於判斷使用者狀態,element-ui 元件處理一些錯誤報錯提示。該檔案封裝暴露了get、post、檔案上傳方法。
import axios from "axios"; import store from "../store"; import { Message, MessageBox } from "element-ui"; let baseURL = "http://127.0.0.1:3000/"; // 建立axios例項 const service = axios.create({ baseURL: baseURL, timeout: 5000, // 請求超時時間 headers: { "Content-Type": "application/json;charset=UTF-8" }, }); // axios.defaults.withCredentials = true; // 若跨域請求需要帶 cookie 身份識別 axios.defaults.headers.post["Access-Control-Allow-Origin-Type"] = "*"; // 允許跨域 const err = (error) => { if (error.response) { let data = error.response.data; const token = store.getters.token; switch (error.response.status) { case 403: Message({ message: data.message, type: "error", duration: 5 * 1000, }); break; case 500: if (token && data.message == "Token失效,請重新登入") { MessageBox.confirm( "很抱歉,登入已過期,請重新登入", "確定登出", { confirmButtonText: "重新登入", cancelButtonText: "取消", type: "warning", } ).then(() => { store.dispatch("Logout").then(() => { window.location.reload(); // 為了重新例項化vue-router物件 避免bug }); }); } break; case 404: Message({ message: data.message, type: "error", duration: 5 * 1000, }); break; case 504: Message({ message: data.message, type: "error", duration: 5 * 1000, }); break; case 401: Message({ message: data.message, type: "error", duration: 5 * 1000, }); if (token) { store.dispatch("Logout").then(() => { setTimeout(() => { window.location.reload(); }, 1500); }); } break; default: Message({ message: data.message, type: "error", duration: 5 * 1000, }); break; } } return Promise.reject(error); }; // request攔截器 service.interceptors.request.use( (config) => { const token = store.getters.token; if (store.getters.token) { config.headers["X-Token"] = token; } return config; }, (error) => { // Do something with request error console.log(error); // for debug Promise.reject(error); } ); // respone攔截器 service.interceptors.response.use((response) => { console.log("response.data", response.data); return response.data; }, err); /* * get請求 * url:請求地址 * params:引數 * */ export function get(url, params = {}) { return new Promise((resolve, reject) => { console.log("process.env.BASE_API", process.env.BASE_API); service({ url: url, method: "get", params: params, }) .then((response) => { resolve(response); }) .catch((error) => { reject(error); }); }); } /* * post請求 * url:請求地址 * params:引數 * */ export function post(url, params = {}) { return new Promise((resolve, reject) => { service({ url: url, method: "post", data: params, }) .then((response) => { resolve(response); }) .catch((error) => { reject(error); }); }); } /* * 檔案上傳 * url:請求地址 * params:引數 * */ export function fileUpload(url, params = {}) { return new Promise((resolve, reject) => { console.log("@@@@@@@@@@@params", params); service({ url: url, method: "post", data: params, headers: { "Content-Type": "multipart/form-data" }, }) .then((response) => { resolve(response); }) .catch((error) => { reject(error); }); }); } export default { get, post, fileUpload, };
然後建立api資料夾,如果介面過多可以對介面進行模組化管理,比如我這 api 下面建立 login.js 檔案。
import { get, post,fileUpload } from "../utils/request"; // 登入 export const login = (params) => { return get("/user/login", { ...params }); }; // 查詢使用者資訊 export const getUserInfo = (params) => { return get("/user/userInfo", { ...params }); }; // 上傳音訊檔案 export const addRadioApi = (params, file) => { return fileUpload("/radio/addRadio", { params, file }); };
最後在你的vue檔案中就可以使用了,login.vue中使用如下:
import { login } from "../../api/login"; login({ name: "123", password: "123456" }) .then((res) => { //登入請求後操作 }) .catch((error) => { //異常處理 });
總結
以上就是本文的全部內容,希望給讀者帶來些許的幫助和進步,方便的話點個關注,小白的成長踩坑之路會持續更新一些工作中常見的問題和技術點。