番外篇:axios相关 以及axios调用数据后台接收不到参数引发的 Request Payload 和formData 学习
前言
当接触并使用axios调用数据成功后,一般不会去研究axios与之前的ajax 有啥区别吧!公司用过程处理的数据,用ajax能顺利调用,但是换成axios就不成立,一番探究,发现确实有盲区!!
简介
大体区分 什么是FormData?什么是RequestPayload?直接通过图例说明
Request Payload
更准确的说是http request的payload body
。一般用在数据通过POST
请求或者PUT
请求。它是HTTP
请求中空行的后面那部分。
一个请求伴随着header设置为Content-Type: application/json
时候,看起来可能像这样:
POST /some-path HTTP/1.1 Content-Type: application/json { "foo" : "bar", "name" : "John" }
如果你正常请求一个ajax。浏览器会简单的将你提交的内容作为payload
展示出来,这就是它所能做的,因为它不知道数据来自哪里。
如果你提交了一个html表单并且配置上了method="post"
,并且设置了Content-Type: application/x-www-form-urlencoded
或者Content-Type: multipart/form-data
。那么你的请求可能长这个样:
POST /some-path HTTP/1.1 Content-Type: application/x-www-form-urlencoded foo=bar&name=John
所以区别就是,他们只是因为Content-Type
设置的不同,并不是数据提交方式的不同,这两种提交都会将数据放在message-body
中。但是chrome浏览器的开发者工具会根据这个ContentType区分显示方式。
传统的Form表单提交
场景构造
<form action="/" method="POST">
<input name="name" type="text">
<input name="password" type="text">
<button>提交</button>
</form>
点击提交,就会触发浏览器的提交功能,请求形式如下
注意点
可以看到Content-Type
为application/x-www-form-urlencoded
。
值得形式是以key1=value1&key2=value2
的形式提交的。
传统的ajax提交
场景构造
function submit2() {
var xhr = new XMLHttpRequest();
xhr.timeout = 3000;
var obj = {a: 1, b: 2};
xhr.open('POST', '/');
xhr.send(obj);
}
首先我们构造一个简单的函数,然后触发它。通过chrome反馈来看:
注意点
1.默认的Content-Type
为text/plain
。
2.Request Payload会对非字符串做字符串转换。
3.通过xhr.send(JSON.stringify(obj));
可修正要发的内容
axios方式提交
场景构造
由于axios已经是vue、react的准标配请求方式了,所以这里探究一下它。
首先我门看axios的文档,当post提交时候可以传递什么类型参数:
注意这个类型,我们分别构造两个场景。对应它。
function submit3() {
var sence1 = 'name=123&val=456';
var sence2 = {name: 123, val: 456};
axios.post('/', sence1)
}
分别传递字符串与对象,提交post请求,然后观察结果:
场景1——传递字符串时候的结果:
场景2——传递对象的结果:
注意点
1.当我们传递字符串的时候,Content-Type
自动转为xxx-form-xxx
的形式。当为对象的时候,自动转化为xxx/json
。
2.字符串的时候以key1=val1&key2=val2
的形式体现,对象以JSON字符串形式体现。
Content-Type的差异
1.传统的ajax请求时候,Content-Type
默认为"文本"类型。
2.传统的form提交的时候,Content-Type
默认为"Form"类型。
3.axios传递字符串的时候,Content-Type
默认为"Form"类型。
4.axios传递对象的时候,Content-Type
默认为"JSON"类型
解决方式 axios 参数为payload的解决方法
axios默认的格式是Request Payload
而如果后台使用Httpservlet时使用request.getParameter时只能拿到格式为formData的数据,这是就需要进行数据转换。
1. 添加头部headers
axios 设置 axios的headers设置放在了axios的构造中才设置成功.
axios.post('http://localhost:3000/api/goods/get',qs.stringify(data),{ headers: { 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8' } }).then(res=>{ _this.msg = res.data },err =>{ console.log(err) })
2. 在Browser环境下
2.1 利用qs.stringify()处理参数
var qs = require('qs'); axios.post('/foo', qs.stringify({ 'bar': 123 });
<script src="/your-path/qs.min.js"></script> axios({ url: url, method: 'post', data: Qs.stringify(params) }) .then(function (resp) { // }) .catch(function (err) { // })
2.2 利用 URLSearchParams API 处理post参数
const params = new URLSearchParams(); params.append('param1', 'value1'); params.append('param2', 'value2'); axios.post('/foo', params);
查看 URLSearchParams 兼容性,还可以使用pollify
3. 在node环境下
可以使用querystring 模块
const querystring = require('querystring'); axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
或者使用qs.stringify(),qs同样可以在node中使用
2020.1.14补充
security只能接收form提交,由于我用的axios,所以需要模拟form提交
//方式 headers: { 'Content-Type': 'application/x-www-form-urlencoded' } //以及data格式需要转换一下 transformRequest: [function (data) { let ret = '' for (let it in data) { ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&' } return ret }],
参考 https://segmentfault.com/a/1190000018774494
2020-2-14 vue项目使用axios发送请求让ajax请求头部携带cookie的方法
vue项目时遇到登录权限问题,开始有个登陆的服务,返回cookie,以后的所有请求头部需要携带这个cookie,否则所有服务被拒绝访问。
axios官网的 说明
// `withCredentials` 表示跨域请求时是否需要使用凭证 withCredentials: false, // 默认的
简单方法:
import axios from 'axios' axios.defaults.withCredentials=true;//让ajax携带cookie Vue.prototype.$axios = axios;
OR
接下来 遇到新的问题
虽然开启了携带cookie,但是在项目的域名中没有看到 相应的cookie,如图所示
百度寻找到的观点汇总
说法一:使用mockjs,他会劫持cookie,通过给mockjs配置withCredentials 参数即可携带cookie:
import Mock from 'mockjs';
Mock.XHR.prototype.withCredentials = true;
简评:这个说法我没事有去实践,直接关闭了mockjs,本来用的也不多
说法二:前端请求的域名和cookie的域相同吗 不相同的话 是不会自动带cookie的,
简评:这个说法得到解决,正如上图,刚开始两个域名不相同,我在localhost下就是看不到所要的cookie,当在浏览器中单独打开接口服务的域名就能看到,后来,后台同志一番操作,我在localhost下看到了 接口服务的cookie,实现了携带多个域名的cookie。
666