axios請求頭設(shè)置常見Content-Type和對應(yīng)參數(shù)的處理方式
一、Content-Type
首先要明確的一點(diǎn)是,我們在項(xiàng)目中調(diào)用接口,通常是以對象的數(shù)據(jù)格式傳給自己封裝的http請求函數(shù)的。
1 application/json
現(xiàn)在的前后端分離項(xiàng)目基本上都是使用的這個(gè)進(jìn)行數(shù)據(jù)傳遞。
axios默認(rèn)Content-type是采用application/json;charset=UTF-8,無需設(shè)置直接把對象傳進(jìn)去即可
當(dāng)然,也可以在請求攔截器中轉(zhuǎn)化成json后再發(fā)請求(但是不能用qs.stringify):
config.data = JSON.stringify(config.data)
2 application/x-www-form-urlencoded
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
用于表單的提交。
值得注意的是,ajax 中(不是axios哈), contentType都是默認(rèn)的值:application/x-www-form-urlencoded。
特點(diǎn)是提交的參數(shù)按照 key1=val1&key2=val2 的方式進(jìn)行編碼,key 和 val 會(huì)進(jìn)行了 URL 轉(zhuǎn)碼。
而要實(shí)現(xiàn)這種參數(shù)的序列化,最簡單的方法是引入qs庫。
做如下的配置。
import Qs from "qs" // 創(chuàng)建axios實(shí)例 const service = axios.create({ baseURL: process.env.VUE_APP_baseUrl, timeout: 5000, ...//其他配置 //transformRequest用來對請求參數(shù)提前進(jìn)行處理 transformRequest: [data => Qs.stringify(data, { indices: true })] //Qs.stringify將參數(shù)序列化成key=value&key=value的形式,indices: true是配置參數(shù)有傳數(shù)組的時(shí)候,以下標(biāo)的形式 })
比如說,當(dāng)我們傳遞的參數(shù)是:
{ title:'標(biāo)題', list:[1,2,3] }
則會(huì)被轉(zhuǎn)化成:title=標(biāo)題&list[0]=1&list[1]=2&list[2]=3的形式。
Qs.stringify(data, { indices: true }//這個(gè)如果用false的話。傳數(shù)組就是title=標(biāo)題&list=1&list=2&list=3的形式了,也就是不帶索引。
結(jié)合上文,在content-tyoe=application/x-www-form-urlencoded時(shí),我們在頁面中傳的是對象,然后通過Qs.stringify把參數(shù)轉(zhuǎn)換成key=value的形式了,這才可以發(fā)出正確的http請求。
另外,Qs.stringify配置的場合也可以有多個(gè)。
如下圖在axios中進(jìn)行配置。
3 multipart/form-data
這也是一個(gè)常見的 POST 數(shù)據(jù)提交的方式。我們使用表單上傳文件時(shí),就要讓 form 的 enctype 等于這個(gè)值。
這種方式一般用來上傳文件,各大服務(wù)端語言對它也有著良好的支持。
這個(gè)和application/x-www-form-urlencoded的區(qū)別在于一個(gè)適合傳字段鍵值,一個(gè)適合傳文件。
二、qs.sringify和JSON.stringify的區(qū)別
假設(shè)我要提交的數(shù)據(jù)是:
var a = {name:'hehe',age:10};
qs.stringify序列化結(jié)果如下
name=hehe&age=10
而JSON.stringify序列化結(jié)果如下:
"{"a":"hehe","age":10}"
三、項(xiàng)目中的實(shí)際應(yīng)用
這個(gè)項(xiàng)目呢,大多數(shù)post請求,后端的接口設(shè)計(jì)的是application/x-www-form-urlencoded類型的content-type。
唯獨(dú)有一個(gè)接口設(shè)計(jì)的是application/json。
但是我最開始content-type的設(shè)置是在全局的axios中進(jìn)行配置的,全都配置成application/x-www-form-urlencoded。
于是需要分類下,使用application/x-www-form-urlencoded的時(shí)候,需要key-value序列化處理,而另一種application/json的則不需要。
import axios from "axios" import { Message as showMessage } from "element-ui" import errorCode from "./errorCode" // import store from "@/store" import Qs from "qs" // axios.defaults.headers["Content-Type"] = "application/json" //底下創(chuàng)建axios實(shí)例時(shí)配置了,這個(gè)不用重復(fù)配置,再說,這也是axios的默認(rèn)配置 export default function request(options) { return new Promise((resolve, reject) => { // 創(chuàng)建axios實(shí)例 const service = axios.create({ // 表示請求URL公共部分,它會(huì)讀取這里的值,然后拼接上頁面使用的url baseURL: process.env.VUE_APP_baseUrl, timeout: 5000, withCredentials: false, // 跨域請求時(shí)是否需要cookie等憑證 responseType: "json", params: {}, maxContentLength: 2000, validateStatus: status => status >= 200 && status < 300, //默認(rèn)值 maxRedirects: 5, //最大允許重定向次數(shù) headers: { //公共請求頭配置,本項(xiàng)目請求頭大多數(shù)接口是這個(gè),所以這里可以配置一下,對于特殊接口單獨(dú)配置 "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" } // transformRequest: [data => Qs.stringify(data, { indices: true })] //將參數(shù)key=value序列化,因?yàn)楸卷?xiàng)目有的接口需要json/對象傳參數(shù),這里就不能這樣直接全局配置,否則有的接口會(huì)報(bào)400(因?yàn)槟惆裫son或者是對象類型的數(shù)據(jù),在這里key=value序列化了) }) // request攔截器 service.interceptors.request.use( config => { switch (config.method) { case "get": if (!config.params) { config.params = {} } break case "post": if (!config.data) { config.data = {} } if (config.type === "keyValue") { config.data = Qs.stringify(config.data) //配套application/x-www-form-urlencoded使用 } else { config.headers["Content-Type"] = "application/json" //配套application/json使用 } break default: } console.log(`【request】url:${config.url},data:${config.data} `) return config }, error => { console.log(error) Promise.reject(error) } ) // 響應(yīng)攔截器 service.interceptors.response.use( res => { // 未設(shè)置狀態(tài)碼則默認(rèn)成功狀態(tài) const code = parseInt(res.data.code) || 0 // 獲取錯(cuò)誤信息 const msg = res.data.msg || errorCode[code] || errorCode["default"] if (code != 0) { showMessage({ message: msg, type: "error" }) reject(new Error(msg)) return } else { resolve(res.data) //獲取到成功的響應(yīng)了,就把結(jié)果resolve出去 } }, error => { console.log("err" + error) let { message } = error if (message == "Network Error") { message = "網(wǎng)絡(luò)異常,請檢查網(wǎng)絡(luò)" } else if (message.includes("timeout")) { message = "系統(tǒng)接口請求超時(shí),請檢查網(wǎng)絡(luò)" } else if (message.includes("Request failed with status code")) { message = "系統(tǒng)接口" + message.substr(message.length - 3) + "異常" } showMessage({ message: message, type: "error", duration: 5 * 1000 }) return reject(error) } ) service(options) }) }
然后請求的封裝:
import request from "./request.js" import { Loading } from "element-ui" let http = { /** post 請求 * @param {接口地址} url * @param {請求參數(shù)} params * @param {請求的參數(shù)處理類型} * keyValue:默認(rèn)的application/x-www-form-urlencoded,使用qs.stringify序列化。 * json:使用application/json,不用處理參數(shù) */ post: function (url, params, type = "keyValue") { let loadingInstance = Loading.service({ lock: true, text: "請稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", fullscreen: false, customClass: "loadingClass" }) return new Promise((resolve, reject) => { request({ url, method: "post", data: params, type }) .then(response => { loadingInstance.close() resolve(response) }) .catch(error => { loadingInstance.close() reject(error) }) }) } } export default http
頁面中使用application/json的接口的調(diào)用:
async newDog() { const that = this let params = { ...this.petForm } try { let res = await that.$http.post("/dog/newDog", params, "json") console.log("--接口請求成功--", res) that.$message({ message: "接口請求成功", type: "success" }) } catch (err) { console.log("報(bào)錯(cuò)了:", err) } },
大致的設(shè)計(jì)思路:
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue相同路由跳轉(zhuǎn)強(qiáng)制刷新該路由組件操作
這篇文章主要介紹了vue相同路由跳轉(zhuǎn)強(qiáng)制刷新該路由組件操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08Vue3+Vite項(xiàng)目引入Bootstrap5、bootstrap-icons方式
這篇文章主要介紹了Vue3+Vite項(xiàng)目引入Bootstrap5、bootstrap-icons方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10Vue中Axios從遠(yuǎn)程/后臺(tái)讀取數(shù)據(jù)
今天小編就為大家分享一篇關(guān)于Vue中Axios從遠(yuǎn)程/后臺(tái)讀取數(shù)據(jù),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01關(guān)于delete和Vue.delete的區(qū)別及說明
這篇文章主要介紹了關(guān)于delete和Vue.delete的區(qū)別及說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue + el-tree 實(shí)現(xiàn)插入節(jié)點(diǎn)自定義名稱數(shù)據(jù)的代碼
這篇文章主要介紹了vue + el-tree 實(shí)現(xiàn)插入節(jié)點(diǎn)自定義名稱數(shù)據(jù)的代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12vue3 ts組合式API異常onMounted is called when&
這篇文章主要為大家介紹了vue3 ts組合式API異常onMounted is called when there is no active component問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Vue項(xiàng)目發(fā)布后瀏覽器緩存問題解決方案
在vue項(xiàng)目開發(fā)中一直有一個(gè)令人都疼的問題,就是緩存問題,這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目發(fā)布后瀏覽器緩存問題的解決方案,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-09-09