公司目前項目並沒有完全實現前後分離的開發模式,在使用vue開發頁面的時候,一度使用引入vue.js + zepto.js的方式,請求一直是用
$.ajax()
的方式。爲了向vue環境靠攏,引入了vue.axios。但是這種方式在用POST傳參的時候,還是踩了不少坑。
使用的時候:
axios.post('/user', {
foo: 'foo',
bar: 'bar'
})
.then(function (res) {
console.log(res);
})
.catch(function (error) {
console.log(error);
});
這樣傳參數,後臺說接收不到,並且前臺查看請求參數的時候,參數的格式還是Request Payload。這在用zepto的$.ajax()
方式的時候是從來沒有過的。後來查了下資料,原來zepto的ajax方式在傳參的時候,默認設置了Content-Type=application/x-www-form-urlencoded
,服務器能夠正確解析,後臺也不用做其他多餘設置。而axios默認的則是Content-Type=text/plain
,如果前後端都不處理的話,請求是無法成功的(其實當時自己並沒有認真看axios的官方文檔,其實官方文檔已經明確說明了這一點,並且給出瞭解決方案)。
方案一:
最初的方案是前臺傳JSON格式的數據過去;設置'Content-Type': 'application/json;charset=UTF-8'
,大概:
axios.post('/user',JSON.stringify(params),{
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
})
.then(function (res) {
console.log(res);
})
.catch(function (error) {
console.log(error);
});
並且後臺改變其接收參數的方式改爲@RequestBody
。
此方法主要參考該博客:https://blog.csdn.net/CarryBest/article/details/80079364
該博客有個問題,就是接收單個參數的時候,是可行的,但是要是接收多個參數,仍然會報錯。解決方法是隻要後臺設置接收的參數爲Map類型或是多個參數組成的類的這種類型(對後臺不是很瞭解,大概是這樣。。)
方案二:
後來後臺反饋,這種方法每個接口都要設置,很麻煩,詢問我有沒有更好的方法,隨後我又自己查閱官方文檔,原來官方給出瞭解決方案。戳這裏,看官方文檔。
使用URLSearchParams
的API:
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
但是該API的瀏覽器兼容性不是很理想,不過有polyfill,提供了兼容性方案。(https://github.com/WebReflection/url-search-params )
方案三:
或者引用qs來encode 傳入的參數。(https://github.com/ljharb/qs )
const qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 }));
當然用es6的語法也可以:
import qs from 'qs';
const data = { 'bar': 123 };
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url,
};
axios(options);
方案四:
在node.js裏,還可以引入querystring模塊。(https://nodejs.org/api/querystring.html )
const querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
綜合考慮,上面方法都不適合我這種傳統的引入以vue.js和axios.js進行開發的模式。(適合vue-cli)
方案五:(最終採用方案)
仔細看文檔的時候發現有個transformRequest
參數,類似於攔截器。用於在傳遞參數前對參數進行處理,於是這裏我手動拼接了一下參數,後端無須做任何處理,正常接收就行。
axios.post(url, params, {
transformRequest: [function (data) {
var str='';
for (var key in data) {
str += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + '&';
}
return str;
}]
} ).then(fulfilled).catch(rejected)