目录
- 引言
- 封装ajax
- 案例:使用自封装ajax
- 案例:动态加载瀑布流
- 跨域
- 引言
对于Ajax现在相信大家已经不会陌生了,无论是原生的XMLHttpRequest方式发送还是通过jQuery框架中提供的$.ajax方式。但是从实际工作角度来说并不是所有的公司都喜欢采用上面两种方式进行请求的发送。
其原因在于:
(1)原生的方式过于繁琐,并且大量重复代码。
(2)jQuery的方式虽然方便,但必须引入jQuery框架,
而框架中不是所有的内容都能用到,这就造成了大量无用代码的堆积。占用资源
因此我们自行封装满足于我们需求的Ajax框架就势在必行,这节课我们就一起来封装一个属于我们自己的Ajax框架。
在此之前为了能更好的的理解今天的内容,让我们先一起复习一下前两种方式:
(1)原生Ajax请求
(2)jQuery中的$.ajax()请求
1)原生ajax请求
var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject("");
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
console.log(JSON.parse(xhr.responseText));
}else{
console.log(xhr.statusText);
}
}
}
xhr.open(‘请求类型get/post‘,‘请求地址url‘,true);
xhr.setRequestHeader(‘Content-Type‘,‘application/json‘);
xhr.send(如果post请求则在这些formData);
2), jQuery中的$,ajax()请求
<script src=‘xxx/jquery1.12.3.min.js‘></script>
<script>
//…
$.ajax({
type:‘get|post‘,
url:‘http://xxxx/xxx.php‘,
dataType:‘json‘,
data:‘如果是post请求则必须写‘,
success:function(jsonData){
console.log(jsonData);
},
error:function(err){
console.log(err);
}
});
</script>
好了,让我们暂且先复习到这里。如果你对上面的内容能够掌握的非常熟练的话,就能够在我们刚才书写的过程中感到一丝丝的不舒服的地方。
那就是jq的方式简便快捷又好用,相比之下原生的写法简直麻烦。
而这,正是我们要自行封装Ajax的原因:
因为jq的方式简便快捷,但是jq框架却过于庞大。
所以我们要自行编写一个属于我们自己的,只用于处理Ajax的简便框架。
2,封装ajax
实际上自封装Ajax请求文件,就是将原生Ajax的请求步骤抽象为一个函数,并单独生成一个js文件保存,当用到的时候直接引入这个文件的过程。
很显然这是个一次性的工作,封装完毕之后我们以后直接拿来直接使用即可。
封装Ajax大致分成下列几个步骤:
(1)提供创建xhr对象的兼容性函数。
(2)提供发送请求的对外接口
(3)设计并约定对外接口的参数规格
(4)实现对外接口中参数处理
(5)实现对外接口中响应处理
(6)实现对外接口中发送处理
(7)设置命名空间,避免全局变量污染。
(1)提供创建xhr对象的兼容性函数
a.让我们先创建一个js文件,并命名为EncapsulationAjax.js。(这就是我们的框架文件)
b.在这个文件内部先声明一个无参函数,命名为createXhr。
function createXhr(){}
c.这个函数是为了获得xhr兼容性对象才书写的,因此在里面书写兼容性代码
function createXhr(){
return window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject(‘’);
}
(2)提供发送请求的对外接口
a.声明对外发送请求的接口,命名为ajax。
function ajax(){}
b.为接口设置一个json格式的参数用于接收相关数据,命名为jsonObj
function ajax(jsonObj){}
(3).设计并约定接口的参数规格
(4)实现对外接口中参数处理
a.对外接口中创建xhr对象
function ajax(jsonObj){
var xhr = createXhr();
}
b.根据请求方式设置参数。
function ajax(jsonObj){
var xhr = createXhr();
}
(5)实现对外接口中响应处理
a.根据请求方式设置回调函数。
function ajax(jsonObj){
//…
if(jsonObj.async === true){
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
if(xhr.status == 200){
jsonObj.success(JSON.parse(xhr.responseText));
}else{
jsonObj.error(xhr.statusText);
}
}
}
}
}
(6)实现对外接口中发送处理
a. 调用open+send函数。
function ajax(jsonObj){
//…
xhr.open(obj.method,obj.url,obj.async);
if(obj.method === "post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(obj.data);
}else{
xhr.send();
}
}
(7)设置命名空间,避免全局变量污染
因为我们所编写的js文件中存在大量全局变量,而这样的全局变量会对其他文件中的内容造成不可预估的影响。在js中函数可以划分作用域,因此我们采用自执行函数将整体包裹,避免了内部创建的变量对全局变量造成的影响。
但是这样一来带来的一个重要问题就是,内部创建的函数对外也变成了不可见状态,因此我们可以借助window对象来将内部创建的对外接口设置为“可见状态”.
(function(){
//…
funtion ajax(){
//…
}
window.ajax = ajax;
}());
OK,到此为止一个名为EncapsulationAjax的框架封装完成了。
这个框架归属于我们自己,并且具有我们所期待的一系列特点:
a.轻量级,寥寥几十行代码
b.兼容性,能够处理IE中很多版本的Ajax请求
c.便捷性,参数都是自己规定的,用着方便
d.扩展性,如果还需要更多的功能直接添加进去即可,不会有任何内容冲突。
那么既然已经编写了一个属于我们自己的工具,就让我们来看看在实际工作中他的表现吧!
3,案例:使用自封装ajax
要求:
(1) html文档结构如下:
(2)发送Ajax使用EncapsulationAjax.js提供的方法实现。
(3)php文档内容如下:
if($_POST){
echo json_encode(array(‘info‘=>$_POST, ‘desc‘=>‘post‘));
}else{
echo json_encode(array(‘info‘=>$_GET, ‘desc‘=>‘get‘));
}
Post请求返回结果:
Get请求返回结果
4,案例:动态加载瀑布流
要求:
(1)整体html结构和js部分都和之前的代码没有冲突和区别
只是需要将【原本的模拟数据】变成【真正的Ajax请求来的数据】。
(2)对于获取数据而言,采用get请求。
(3)最后需要将整个处理瀑布流加载过程的代码,放置到success中执行
(4)php后台文件中只需要将图片的路径地址构建,并返回即可。
$imgArr = [‘http://127.0.0.1/waterfall/i1.jpg’,‘http://127.0.0.1/waterfall/i2.jpg’,…];
$finalArr = array(‘desc‘=>‘success‘, ‘imgArr‘=>$imgArr);
echo json_encode($finalArr);
ajax({
method:‘get‘,
url:‘waterfall.php‘,
async:true,
success:function(data){
//…构建瀑布流的代码
},
error:function(error){
console.log(error);
}
});
5.跨域
(1)浏览器同源政策
(2)Ajax跨域
(3)JSONP跨域方案(get请求)
(1).浏览器同源政策
(1)浏览器同源政策
起源:1995年,同源政策由Netscape公司引入浏览器。
含义:最初的目的是某页面所设置的cookie,只能由其“同源”页面打开。
说明:“同源”:协议相同、域名相同、端口相同
例子:http://www.frank.com/sxt/page.html这个网址
协议是:http://
域名是:www.frank.com
端口是:80(默认端口可以省略)。
它的同源情况如下:
http://www.frank.com/sxt2/other.html:同源
http://frank.com/sxt/other.html:不同源(域名不同)
http://v3.www.frank.com/sxt/other.html:不同源(域名不同)
http://www.frank.com:81/dir/other.html:不同源(端口不同)
目的:同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
限制:随着互联网的发展,"同源政策"越来越严格。
目前,如果非同源,共有三种行为受到限制:
(1)Cookie、LocalStorage 和 IndexDB 无法读取。
(2)DOM 无法获得。
(3)AJAX 请求不能发送。
补充:凡事都有利有弊,尽管限制是有必要的,
但在有些情况下合理的用途也会因“同源政策”而受到影响。
因此我们将要为大家介绍的一些规避上述限制的手段,就是【跨域】的由来。
(2)Ajax跨域
描述:Ajax跨域指的是将Ajax请求进行跨域处理,而不是说在Ajax中提供了跨域的方法。
由来:同源政策中明确规定Ajax请求只能发给同源的网址,否则就会发生跨域报错。
解法:除了设置代理之外页面中有三种常见的解决跨域的手段,
而根据我们所掌握的内容来考虑,我们只学习最常见的一种叫做JSONP的方法。
其余另外两种分别叫做webSocket和CORS。
(3)JSONP跨域方式
描述:JSONP是服务器与客户端跨源通信的最常用方法。
最大特点就是简单适用,老式浏览器全部支持,对服务器改造非常小。
本质:实际上利用了script标签引入js文件,并解析执行的原理。
语法:
(1)在html中插入script标签,并利用script标签发起跨源请求
var script = document.createElement(‘script‘);
script.setAttribute("type","text/javascript");
script.src = ‘跨源url地址?【前后端约定回调关键词】=【回调函数名】‘;
document.body.appendChild(script);
(2)在服务器对应php文件中通过拼接字符串,模拟函数调用。
并将要返回数据通过回调函数参数返回。
$response = $_GET[‘前后端约定回调关键词‘];
echo $response."(".json_encode(要返回数据).")";
(3)在html页面中,显式写出回调函数。这样当跨源请求完成后对应回调函数会自动执行。
function 回调函数名(data) {
console.log(data);
};
优点:
(1)由于使用script脚本作为请求,因此实际上请求和传统的引入js脚本没有任何区别。
(2)而在返回的数据中我们也尽量模拟出了js调用函数的语法,
因此只要在页面中声明了回调函数就会自动被调用。
(3)再者作为参数的【服务器端】的JSON数据,在js中是被直接识别为对象,
因此在回调函数中也避免了使用JSON.parse的步骤。