AJAX的调用还十分麻烦,步骤比较繁琐,在日常开发一般会将其进行封装,所以接下来封装下AJAX功能相关步骤函数,以后使用直接调用即可,同时大大提高了开发效率。
为了使用方便,接下来封装AJAX的get和post
封装:基本模板与传参
此时调用模板时,如下所示
封装1:建立异步对象
封装2:判断请求类型
get请求类型传值方式是将数据拼接到路由后进行传值,所以接下来需要判断是否传值(对比post请求)
1、get请求类型传值方式是将数据拼接到路由后进行传值
2、post请求类型判断是否有传值,如果有则send发送至服务器,没有则不发
封装3:注册事件,针对不同状态进行响应,获取返回数据
开发中,也可以将响应,即注册事件步骤,直接移至第一步创建异步对象下,以便更好地监听到状态变化。
封装调用:
接下来外部传参调用下封装的AJAX函数
接下来外部传参调用下封装的AJAX函数
此时控制台测试,便可以输出打印JSON格式数据,所以如果想用JS进一步操作,需要进行反序列化解析即JSON.parse(),然后操作其对页面进行局部更新。
AJAX跨域
跨域简介:
AJAX跨域指的是JS在不同的域之间进行数据传输或通信。
跨域方案:
1、jsonp跨域(重点)----前端处理方法
2、cros跨域-----后台处理
常见跨域场景?
所谓的同源是指,域名、协议、端口均为相同。
JSONP跨域:
jsonp跨域原理:借助网页标签中src属性的跨域特性实现
src简介:src是source的缩写,资源的意思,在html中src表示资源地址,是js文件和图片文件的引入方式,经常引用外部资源,可以实现跨域访问,如下所示
接下来调用下百度搜索接口,如下所示
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/?wd=&cb=
注意: 百度接口不太稳定
解析:
wd为搜索关键词,百度搜索功能发送请求类型为get,因为所搜的关键词可以在url中可见。这里先不用回调
将之前代码做下调整,将url改为百度搜索接口,如下所示
注意:
因为是get方式,所以关键词传值需要拼接到url里,即通过data传参,且参数为想要的关键词,然后之前封装好的AJAX会将其进行封装,也就是说最后send对应的接口url为经过封装的AJAX函数拼接后的地址
接下来使用JSONP实现跨域,本质利用src属性的跨域请求资源特性,同理<script></script>
脚本标签也是通过src引入资源,所以可以进行封装处理,实现AJAX的跨域访问远程资源。
接下来做下测试,script标签引入接口文件,并在接口加入回调函数,然后在页面定义调用
测试结果如下
此时虽然有报错,但是已经没有报跨域错误,接下来将调用位置做下调整,先定义声明函数,然后再进行传值,如下所示
修改后测试结果如下
AJAX跨域-CROS
除了通过JSONP解决跨域外,常见的方法还包含CROS方法
【前言】
CROS需要在后台进行配置→允许所有域名访问
1、PHP后台仅仅需要添加一句代码即可 表示允许所有域名访问。
2、JAVA后台需要下载CROS包,然后进一步配置
接下来我们用一个案例详细了解一下jsonp
需求:
输入框输入关键字同时,会利用AJAX不断跟后台进行交互,进而实现局部更新页面关键词功能,因为涉及跨域,所以这里用JSONP方式解决
接口URL:
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/?wd=&cb=
因为百度搜索接口不太稳定,接下来改用电商接口
淘宝商品搜索建议
http://suggest.taobao.com/sug?code=utf-8&q=商品关键字&callback=cb
PS:callback是回调函数设定
JSONP跨域案例
第一步:
首先编写模板代码,设置静态样式,如下所示
功能分析:
在输入框中输入关键字后,底下出现对应的智能匹配关键词
例如,在输入框输入“333”
第二步:
编写键盘事件,监听按键松开,获取输入值
第三步:
获取到输入值之后,需要动态写入内容。接下来使用JSONP跨域,所以需要动态创建标签。
接口:https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/?wd=&cb=
关键字为wd,回调函数为cb,
动态创建script标签,利用JSONP原理跨域调取数据
script标签筛选去重
目前为止,输入关键字后控制台会输出打印相关数据,例如输入7后再次输入8,如下所示
日常使用时,只需要创建一个script标签即可,后期修改关键字时,只需要修改src就行了。所以接下来判断下script标签是否重复,做判断处理。
第五步:
动态创建元素,创建关键词智能匹配列表
接下来将ul高度改为auto自动
接下来简单设置下样式即可。
第六步:
添加跳转事件
目前为止,点击智能搜索列表项,无法完成跳页,此时需要另外一个搜索接口https://www.baidu.com/s?&wd=
JSONP限制
优点:
1、它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,JSONP可以跨越同源策略
2、兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持
3、在请求完毕后可以通过调用callback的方式回传结果。将回调方法的权限给了调用方,相当于将controller层和view层分开。提供的jsonp服务只提供纯服务的数据,至于提供服务以 后的页面渲染和后续view操作都由调用者来自己定义。如果有两个页面需要渲染同一份数据,只需要有不同的渲染逻辑就可以了,逻辑都可以使用同 一个jsonp服务。
缺点:
1、请求类型:它只支持GET请求而不支持POST等其它类型的HTTP请求
2、不能解决不同域的两个页面之间如何进行JavaScript调用的问题
3、响应状态:jsonp在调用失败的时候不会返回各种HTTP状态码
4、安全性:最大缺点是安全性,假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的。那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。于是无法把危险控制在一个域名下…所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。
跨域
浏览器出于安全的考量(避免恶意网站轻易读取其他网站显示的内容,因为该内容可能含有敏感信息,想象iframe嵌套银行网页)原则上允许跨域写而限制了跨域读。写是指数据的上行/发送(sending request),读是指数据的下行/接收(receiving response)。
然而跨域写也是很不安全的,容易导致CSRF/clickjacking攻击。浏览器已经限制了跨域读,再限制跨域写的话,那互联网的每个页面都成了孤岛。避免非法跨域写需要用到token。
考虑下述情况:
1、指向外部域名的link和通过表单的向外部域发起get请求是一样的,也都是允许的,点击那一刻起,浏览器的当前域名转向了目标网站,也就完全是域内读了。
2、通过表单向外部域发起post请求也是允许的,理由同上,源网站无法读取目标网站的任何内容。
3、AJAX(借助XMLHttpRequest对象)跨域get/post是禁止的,因为使用AJAX就是为了读取响应的内容,这触碰了跨域读的限制。
4、JSONP属于跨域读,且形式限制为get请求,因为它利用了script标签的特性(浏览器认为跨域读脚本是例外,类似的还有img、iframe等等,注意它们共有的src属性)。
因此对于浏览器而言:1和2没有跨域;3遵循了限制跨域读的原则;4属于允许的例外。
分析:
虽然JSONP很好用,但它注定是get请求,get请求有语义要求(幂等)、长度限制(为了兼容限制255字节)、安全隐患(容易受到csrf攻击,csrf的解决必须是post请求配合token使用)
扫盲:CSRF(Cross-site request forgery)跨站请求伪造,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。
那么,如何实现跨域post请求呢?
1、CORS跨域资源共享
概述:Cross-Origin Resource Sharing,W3C制定的跨站资源分享标准。
优点:W3C标准方案
缺点:不兼容老浏览器
注意:若在多个iframe之间跨域通信,优先考虑 window.postMessage(H5 新技术→ 安全地实现Window对象之间的跨域通信)
2、invisible iframe(隐形)
概述:通过js动态生成不可见表单和iframe,将表单的target设为iframe的name以此通过iframe做post提交。提交后由于跨域,无法直接读取响应内容。一般的做法是,iframe内通过js改变自身location的fragment,外部则监听iframe的onload事件,读取fragment的内容。有现成的跨域iframe通信类库,如jQuery PostMessage Plugin。
优点:兼容性佳,facebook,google,新浪已/曾采用
缺点:依赖hack实现,响应数据量大时需要切片、多次设置fragment并轮询,响应频繁时可能失效。
3、server proxy (服务器代理权)
概述:当前域实现一个代理,所有向外部域名发送的请求都径由该代理中转。
缺点:每个使用方都需要部署代理,数据中转低效,对js有侵入。
4、flash proxy(flash 代理权)
概述:利用不可见的swf跨域post提交数据,需要部署crossdomain.xml。例如alirte会自动检测,若用户安装了flash,则以此实现跨域通信。
要求:flash9,缺点:依赖flash
优点:ADOBE标准方案,相对CORS兼容性佳,相对invisible iframe响应数据量较大时优势明显。
跨域post请求:
1、CORS(跨域资源共享)
2、invisible iframe(隐形)
3、server proxy (服务器代理权)
4、flash proxy(flash 代理权)
接下来我们再看一个案例
手机查询接口
http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=手机号
案例:
步骤分析:
1、编写静态页面
2、绑定监听事件,获取输入值
3、调用手机信息查询接口并调用回调函数
4、定义回调函数,检测返回数据
5、解析数据,js操作返回数据,实现页面局部刷新
手机查询接口
http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=手机号
JSONP步骤小结
1、动态创建
2、在页面中,返回的JSON作为参数传入回调函数中,然后通过回调函数来来操作数据,最后在控制台,可以查看到返回的response数据格式为JSON对象格式的,具体需要取出哪些参数,可以根据自己的需要
以上为开发中的步骤,但从原理角度出发,正确解析步骤应该为
1、首先在客户端注册一个callback,然后把callback的名字传给服务器
2、客户端浏览器,解析script标签,并执行返回的 javascript 文档
JSONP小结
(1)JSONP实现跨域请求的原理
简单的说,就是动态创建
JSONP跨域局限
JSONP解决跨域虽然是常用的方法,但也存在很多局限
1、不能接受HTTP状态码
2、不能使用POST提交(默认GET)
3、不能发送和接受HTTP头
4、不能设置同步调用(默认异步)
其最严重的就是不能提供错误处理,如果请求的代码正常执行那么会得到正确的结果。如果请求失败,如404,500之类,那么可能什么都不会发生。即要确定 JSONP 请求是否失败很难,虽然 HTML5 给