小傻 2019-06-26
前端越来越工程化,而ajax是整个前端的核心,所以ES规则和各种封装的工具类越来越多;
借此机会我把http,XMLHttpRequest,ajax,$.ajax,vue-resource,axios做了一个知识大串联,本文主要是侧重将知识串成一条线,自己也复习下,希望也能帮到你们
http是超文本传输协议英文简称,是基于TCP/IP通信协议来传递数据。
1.HTTP是无连接:每次只处理一个请求,处理完毕断开再处理下一个请求;
2.HTTP是媒体独立的:可以处理知道的能处理的数据类型,就是我们在请求的时候需要设置的请求头的内容,HTTP content-type内容
3.HTTP是无状态:就是没有办法记住上一次请求的状态;
1.由于很多需求是要记住上一次请求的状态信息,如登录状态的保持,所以要有对应的解决方案,那就是cookie和session
2.cookie简单的实现过程:后台通过req.header获取请求头的内容===>调用res处理===>cookie写入响应头===>返回数据写入响应体===>结束响应===>响应头响应体;
3.session实现过程:后台调用HttpServletRequest的getSession方法===>生成并发送给客户端session id,调用session相关方法增加内容===>客户端请求携带seession id===>服务端对应session id相应的Session,并重新创建session
域名解析 --> 发起TCP的3次握手(试探并建立TCP/IP连接) --> 建立TCP连接后发起http请求(请求行,请求头,请求主体) --> 服务器响应http请求(响应行,响应头,响应主体)-->四次挥手(中断这次TCP连接)
是ajax的核心,提供了对 HTTP 协议的完全的访问,包括用get,post或head请求的能力,也就是可以理解为XMLHttpRequest对象里面对http协议请求进行了封装,并暴露一些属性和方法。
1.readyState:XMLHttpRequest创建后方法调用的每个阶段对应的状态值,值为0-4,0-->创建对象,1-->请求行执行,2-->请求主体执行,3-->响应头已经接收完,响应主体正在接收,4-->请求完成
2.responseText:响应主体内容
3.responseXML:对请求的响应,解析为 XML 并作为 Document 对象返回。如果响应体不是“text/xml”返回null。
4.status:状态值
5.withCredentials:是一个布尔值, 默认为false, 表示跨域请求中不发送cookies等信息. 当它设置为true时, cookies , authorization headers 或者TLS客户端证书 都可以正常发送和接收. 显然它的值对同域请求没有影响.IE10才支持
onreadystatechange:readyState值改变会触发的事件句柄函数,主要就是监听该对象的每个阶段变化
1.abort():取消响应,如ajax中需要终止请求就是调用该方法,原理就是把 XMLHttpRequest 对象重置为 readyState 为 0 的状态
2.getAllResponseHeaders()/getResponseHeader():返回所有或单个的响应头
3.open(method,url,async,username,password):请求行。
method可以是get,post,head,put和delete,url一般是同源的(不同源就是常说的跨域);
async值默认是true(表示异步的),可以设置为false,表示同步;
username 和 password 参数是可选的,为 url 所需的授权提供认证资格
4.setRequestHeader("Content-type",format):设置请求头,如果请求行的方法是get可不设置
format值一般有四种(主要针对post提交):
默认纯文本:"text/plain; charset=utf-8",其中charset=utf-8可省略
json格式:"application/json"
表单默认:application/x-www-form-urlencoded,浏览器的原生 form 表单,如果不设置 enctype 属性就会以该格式提交,如果是form表单可设置enctype属性为multipart/form-data上传文件
html:text/html
4.send(data):请求主体,发送请求,如果请求行是get时data默认为空
分为XMLHttpRequest Level 1和XMLHttpRequest Level 2
两者的不同看阮大哥的:XMLHttpRequest Level 2 使用指南
全称Asynchronous Javascript And XML,实际上就是利用XMLHttpRequest 对象或者ActiveXObject(兼容IE)实现页面的局部请求数据功能。
1.创建异步对象
let xhr = new XMLHttpRequest();//IE5和6是new ActiveXObject(),IE8,9是XDomainRequest()
2.请求行
xhr.open('get', url);//可以是get,post,head,put和delete
3.请求头(get可省略)
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");//格式见上面XMLHttpRequest请求头方法格式
4.监听响应头和主体
通过onreadystatechange 监听返回状态,通过XMLHttpRequest的getResponseHeader()判断响应头信息,得到对应的响应内容responseText或responseXML,代码如下
/* type:请求方法 data: 发送的数据 url: 请求的url success:回掉函数 */ ajax: function (option) { //1.创建异步对象 var xhr = new XMLHttpRequest(); //2.请求行 if (option.type == 'get' && option.data) { option.url += '?'; option.url += option.data; // 如果是get请求 那么 把data 设置为null 发送的时候 就相当于 发送null option.data = null; } xhr.open(option.type, option.url); //3.请求头(get请求可以省略) if (option.type == 'post' && option.data) { xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); } //4.注册状态改变事件 xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200){ let type = xhr.getResponseHeader('content-type'); if (type.indexOf('json') != -1) { option.success(JSON.parse(xhr.responseText)); return; } if (type.indexOf('xml') != -1) { option.success(xhr.responseXML); return; } option.success(xhr.responseText); } } //5.发送请求 xhr.send(option.data); }
1.发送数据形式不同:
get是拼接到URL后面,默认形式是QueryString,
post默认是Request Payload(因为XMLHttpRequest默认的请求头格式是text/plain),一般设置请求头设置了application/x-www-form-urlencoded就转化为From Data格式,
为什么要设置转化?Request Payload后台通过request.getParameter(name)无法获取数据
2.发送数据大小:
get是拼接到URl上的,IE对URL长度的限制是2083字节(2K+35字节),火狐和谷歌无限制,服务器可限制
post前端无限定大小,服务器可限制
3.安全性:
post比get安全,因为get是在URL中,所以数据暴露在外面,而且一般浏览器会缓存浏览的URL
如果要绝对的安全可以使用https传输
就是不同源,同源指的是URL(统一资源定位符)的协议名,域名和端口名相同
Cookie、LocalStorage和IndexDB(浏览器自带的一个数据库)无法获取;
DOM无法获得;
AJAX请求不能发送;
所以同源策略设置的目的就是为了保证用户信息的安全,防止浏览器受到XSS、CSFR等攻击。
一看8种,其实常用的只有三种,前面三种是比较常用的:
1.JSONP:就是利用<script>的src属性不受同源的限制,对应的用callback接收返回值;
2.CORS(跨域资源共享):
<1>简单请求:
服务器设置:前端设置XMLHttpRequest的withCredentials为true,服务器设置Access-Control-
Allow-Credentials: true
<2>非简单请求:除了简单请求之外的,请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json
跨域方法:浏览器先预检,服务器回应
更多详情参照阮老师的跨域资源共享 CORS 详解
<3>反向代理:
原理:而nginx通过检测url前缀,把http请求转发到后面真实的物理服务器。并通过rewrite命令把前缀再去掉。这样真实的服务器就可以正确处理请求,并且并不知道这个请求是来自代理服务器的
<4>WebSockets
WebSocket是HTML5新出的一种通信协议,是http协议支持长连接的一个优化,使用ws://(非加密)和wss://(加密)作为协议前缀。主要是该协议不实行同源政策,只要服务器支持
详情参照:WebSocket - Web API 接口 | MDN
大家有没想一个问题,WebScoket无同源限制难道不会有攻击吗?
其实那些跨域的URL是需要服务器授权的,没有授权的则无法访问.
详情参照:WebSocket通信协议应用安全问题分析
前面5种都是支持ajax请求的跨域方法
JSONP只适用于get方法做跨域,CORS和反向代理适用于所有请求方法;
JSONP适合所有浏览器,CORS只支持IE10及以上
WebSocket只能发送纯文本数据,所以如果发送复杂的格式的数据可以用JSON.STRINGFY来把数据序列化一下,而且有IE10及以上才支持
<5>document.domain + iframe 跨域:
只可以非同源共享cookie,DOM
<6>window.name + iframe 跨域
<7>跨文档通信API(Cross-document messaging)之window.postMessage
HTML5新引入的,可以跨域LocalStorage
<8>片段识别符
片段识别符指的是,URL的#号后面的部分,如果只是改变片段标识符,页面将不会重新刷新,父子窗口可以相互改变该标识符
详情参照:浏览器的跨域问题以及解决方案
常见的三种用法:
1.$.get
$.get(url,data,success(response,status,xhr),dataType) //data为传入的数据 //"xml","html","text","script","json","jsonp", eg: $.get("test.cgi", { name: "John", time: "2pm" }, function(data){ alert("Data Loaded: " + data); });
2.$.post
$.post(url,data,success(data, textStatus, jqXHR),dataType)
3.$.ajax
$.ajax({ //常四个参数和一个回调函数 url: url, data: data, success: success, dataType: dataType });
更多参数和回调函数见:jQuery ajax - ajax() 方法
4.三种对比
$.get和$post是$.ajax的简写形式,三种方法跨域的方法都是jsonp
1.语法
fetch(url, { method: "POST",//请求方法 body: JSON.stringify(data),//请求主体 headers: { "Content-Type": "application/json"//请求头 }, mode:cors,//请求的模式,值还可为no-cors 或者 same-origin credentials: "same-origin"//请求权限 }).then(function(response) { response.status //=> 请求结果参数number 100–599 response.statusText //=> 请求结果状态String response.headers //=> 返回头部信息Headers response.url //=> String response.text()//方法还有json(),blob(),arrayBuffer(),formData() .then(function(responseText) { ... }) }, function(error) { error.message //=> String })
2.fetch的get使用
fetch(url)//options省略表示get .then(function(response) { return response.json();//生成json, }).then(function(data) { console.log(data); }).catch(function(e) { console.log("Oops, error"); });
3.fetch的post使用
fetch('/users', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Hubot', login: 'hubot', }) })
fetch的详细使用:【译】fetch用法说明
4.fetch怎么实现跨域
mode的三个值的含义
same-origin:该模式是不允许跨域的,它需要遵守同源策略,否则浏览器会返回一个error告知不能跨域;其对应的response type为basic。
cors: 该模式支持跨域请求,顾名思义它是以CORS的形式跨域;当然该模式也可以同域请求不需要后端额外的CORS支持;其对应的response-type为cors。
no-cors: 该模式用于跨域请求但是服务器不带CORS响应头,也就是服务端不支持CORS;这也是fetch的特殊跨域请求方式;其对应的response-type为opaque
所以服务器支持则可以设置CORS,不支持可以设置no-cors
1.使用过程
/*安装*/ npm install vue-resource --save /*引入Vue框架*/ import Vue from 'vue' /*引入资源请求插件*/ import VueResource from 'vue-resource' /*使用VueResource插件*/ Vue.use(VueResource)
2.$http.get
this.$http.get('/someUrl', [options]).then((response) => { // 响应成功回调 }, (response) => { // 响应错误回调 });
3.options参数值
如果Web服务器无法处理PUT,PATCH和DELETE这种REST风格的请求,可以启用enulateHTTP现象。启用该选项后,请求会以普通的POST方法发出,并且HTTP头信息的X-HTTP-Method-Override属性会设置为实际的HTTP方法
3.$http.post
post请求默认的请求类型是request payload,根据上面get和post对比中提到request payload形式对后台获取数据不友好,所以需要将emulateJSON设置为true
4.拦截器(inteceptor)
Vue.http.interceptors.push({ request: function ( request ) { // 更改请求类型为POST request.method = 'POST'; return request; }, response: function ( response ) { // 修改返回数据 response.data = [{ custom: 'custom' }]; return response; }
});
5.跨域
JSONP:
Vue.http.jsonp(url,{params: {name='张三'},jsonp:"_callback"})
params是要发送的数据对象,jsonp是设置回调的名称,也就是上面的callback名称;(不设置默认为callback),后台获取发送过去的”_callpack”的值,将这个值拼接到返回的json数据上
CORS:
如果浏览器支持XMLHttpRequest Level 2在Broswer就可以设置
Vue.http.options.xhr = { withCredentials: true }
服务端启用支持
反向代理:在vue项目下的 config/index.js 文件里面配置代理proxyTable
1.使用过程
/*安装*/ npm install axios --save /*引入Vue框架*/ import Vue from 'vue' /*引入资源请求插件*/ import axios from 'axios' /*使用VueResource插件*/ Vue.use(axios)
2.axios.get
axios#get(url[,config]) axios.get(getUrl, { params: { 'getAjaxDataObj1': getAjaxData.obj1,//obj1为getAjaxData的一个属性 'getAjaxDataObj2': getAjaxData.obj2 } }).then(data=>{ //成功返回 }).catch(err=>{ //错误返回 })
3.axios.post
axios#post(url[,config]) axios.post(postUrl, { 'postAjaxDataObj1': postAjaxData.obj1,//obj1为postAjaxData的一个属性 'postAjaxDataObj2': postAjaxData.obj2 }).then(data=>{ //成功返回 }).catch(err=>{ //错误返回 })
4.axios.post请求的问题
默认请求数据格式是application/json,如果后台不支持这种form Data形式,则需要:
在Browser中 <1.>设置请求头格式 在config配置headers: {'X-Requested-With':'XMLHttpRequest'}, <2.>格式化数据 方法一: 并引入axios里面内置的qs,不需要重新下载 import qs from 'qs' axios.post('/foo', qs.stringify({ 'bar': 123 })); 方法二: let params = new URLSearchParams(); params.append('param1', 'value1'); params.append('param2', 'value2'); axios.post('/foo', params); 在node中 let querystring = require('querystring');//直接引入node的querystring模块 axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
4.config的常见参数:
//`url`是请求的服务器地址 url:'/user', //`method`是请求资源的方式 method:'get'//default //如果`url`不是绝对地址,那么`baseURL`将会加到`url`的前面 //当`url`是相对地址的时候,设置`baseURL`会非常的方便 baseURL:'https://some-domain.com/api/', //`headers`选项是需要被发送的自定义请求头信息 headers: {'X-Requested-With':'XMLHttpRequest'}, //`withCredentails`选项表明了是否是跨域请求 withCredentials:false,//default
详情请见:axios
4.axios的inteceptor(拦截器)
主要分为请求和响应两种拦截器,请求拦截一般就是配置对应的请求头信息(适用与常见请求方法,虽然ajax的get方法没有请求头,但是axios里面进行啦封装),响应一般就是对reponse进行拦截处理,如果返回结果为[]可以转化为0
axios.interceptors.request.use(config => { config.headers.cityCode = window.sessionStorage.cityCode //jsCookie.get('cityCode') return config }, axios.interceptors.response.use((response) =>{ let data = response.data if(response.request.responseType === 'arraybuffer'&&!data.length){ reponse.date=0 } })
5.跨域
CORS:设置config里面的withCredentails为true
反向代理:和vue-resource一样
JSONP:axios里没有进行封装,但是github推荐了一种方法:
详情请见:github中JSONP的实现
我看了一下他的博客,大概意思是vue-resource之前是官方维护的,但是不同的路由和状态管理,ajax并不是一个问题域,需要与Vue核心深度整合,一个纯粹的第三方库能很好解决这个问题
原文链接(需要翻墙):Retiring vue-resource
很开心你还能看到这里,整个文章概念还是挺多的,
希望这次梳理对你串联http,ajax,XMLHttpRequest,$ajax,vue-resource和axios有帮助。如果文章内容有错误欢迎指出交流!
可以先收藏着,想看的时候再慢慢体会。
http://www.runoob.com/http/ht...
http://www.ruanyifeng.com/blo...
http://www.ruanyifeng.com/blo...
https://developer.mozilla.org...
http://www.techweb.com.cn/net...
http://blog.csdn.net/u0130843...
http://www.w3school.com.cn/jq...
https://segmentfault.com/a/11...
https://www.jianshu.com/p/df4...
https://github.com/axios/axio...
https://medium.com/the-vue-po...
结束数据方法的参数,该如何定义?-- 集合为自定义实体类中的结合属性,有几个实体类,改变下标就行了。<input id="add" type="button" value="新增visitor&quo
本文实例讲述了php+ ajax 实现的写入数据库操作。分享给大家供大家参考,具体如下:。<input class="tel" type="text" placeholder="请输入您的手机号码&q