1.Ajax封装方法
自封装Ajax请求文件,其实就是将原生的Ajax的请求代码抽象为一个函数,
然后单独生成一个js文件保存,用到Ajax的时候引入文件,调用函数的过程。
封装Ajax大致步骤如下:
⑴ 提供创建xhr对象的兼容性函数
⑵ 提供发送请求的对外接口
⑶ 设计并约定对外接口的参数规格
⑷ 实现对外接口中参数处理
⑸ 实现对外接口中相应处理
⑹ 实现对外接口中发送处理
⑺ 设置命名空间,避免全局变量污染
2.Ajax封装实现
代码示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>自封装Ajax测试</title> <script src="privyAjaxUnit.js"></script> </head> <body> <button>发送测试</button> <script> var btn=document.querySelector('button'); btn.onclick=function () { myAjax({ type:'post', url:'privyAjax.php', data:{ uName:'Rebecca', uCode:'111111' }, success:function (res) { console.log(res); } }); } </script> </body> </html>
//模拟jQ中的Ajax创建myAjax方法, function myAjax(paramsObj) { //判断参数对象中的请求方式,请求方式为“get”时 if (paramsObj.type.toLowerCase()=='get'){ var arr=[]; for (var ki in paramsObj.data){ //paramsObj.data为对象类型数据,通过for in方法将其转为数组 var str=ki+'='+paramsObj.data[ki]; arr.push(str); } // 由于get方法传参需要是字符串格式,通过join方法将数组转为字符串,并使用“&”拼接。 var paramStr=arr.join('&'); // 将字符串格式的参数拼接到“url”,但拼接之前有必要判断一下调用Ajax时, // url是否已有部分参数或传参符号“?”,通过三目运算使用indexof方法遍历查找“?”。 paramsObj.url+=paramsObj.url.indexOf('?')==-1?'?'+paramStr:'&'+paramStr; // 判断参数对象中的请求方式,请求方式为“post”时 }else if (paramsObj.type.toLowerCase()=='post'){ var formData=new FormData(); for (var ki in paramsObj.data){ formData.append(ki,paramsObj.data[ki]); } }else{ console.log('无该种请求方式!') } // 创建xhr对象 var xhr=window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject(''); xhr.onreadystatechange=function () { if (xhr.readyState==4){ if (xhr.status==200){ //调用回调函数,并将后台返回的数据解析后传参。 paramsObj.success(JSON.parse(xhr.responseText)); } } } // 准备发送请求 xhr.open(paramsObj.type, paramsObj.url, true); // 发送请求 if (paramsObj.type.toLowerCase()=='get'){ xhr.send(null); }else if (paramsObj.type.toLowerCase()=='post'){ xhr.send(formData); }else { console.log('无该种请求方式,请求发送失败!') } } /*自封装Ajax函数的创建过程,本质就是以参数化的形式实现原生Ajax请求, 上述代码中从第4行到第26行,都是为了判断请求方式,进而根据不同的请求方式生成“url”或“ForMData”*/ //myAjax方法创建完成后,可以将其封装到“(function(){}())”这个自执行函数中, /*(function (){ function myAjax(paramsObj) {...} // 可以将创建好的myAjax方法绑定到“window”对象,通过window调用 window.myAjax=myAjax; }());*/
<?php $suc=array('msg'=>'ok'); if($_POST){ $suc['info']=$_POST; }else if($_GET){ $suc['info']=$_GET; }else{ $suc['info']='无此种请求方式'; }; echo json_encode($suc); ?>
3.跨域
所谓跨域,是指前台访问路径不符合同源政策时即为跨域。
同源政策,是两个路径是否在同一台服务器下的判断标准。
判断标准,三要素(网络协议、主域名或IP、端口号)相同则视为同一台服务器,否则反之。
Ajax不能发送跨域请求,出现跨域时会报错。
解决Ajax跨域问题两种常用方法:
⑴ 通过后台请求跨域文件解决,后台不存在跨域问题;
PHP中访问跨域url路径,使用“file_get_contents('跨域url')”方法
后台获取跨域文件后,前台再使用Ajax方法获取后台数据
⑵ 使用“jsonp”通过前台解决。
jsonp解决方案不使用Ajax方法,而是使用其它既具有前后台交互、请求异步以及
链接PHP后台这三个核心功能,又可以访问外部文件的标签替代Ajax。
<script>标签满足上述条件,但需要后台配合实现跨域请求。
代码示例:
<html lang="en"> <head> <meta charset="UTF-8"> <title>跨域请求</title> </head> <body> <button onclick="creatScript()">跨域请求</button> <script> // 第一种方式:通过创建script元素发送请求 /*function creatScript() { var script=document.createElement('script'); script.src='crossServ.php'; document.body.appendChild(script); script.onload=function(){ this.remove(); } }*/ function cross(res) { console.log(res); } </script> <!-- 第二种方式:直接在<script>标签中定义 src 属性值 --> <!-- 为确保后台返回数据时调用的方法与前台定义方法一致,在发送请求时可将方法名一并发送 --> <script src="crossServ.php?callback=cross"></script> </body> </html>
<?php // 通过前台 callback 参数接收方法名。 $fn=isset($_GET['callback'])?$_GET['callback']:'cross'; $info=file_get_contents('http://blog.sina.com.cn'); $info=json_encode($info); echo "{$fn}({$info})"; ?>
4.分页案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>multi-pages</title> <script src="../JScodeFile/jquery-1.8.3.js"></script> <style> .contentUl{ 600px; margin: 50px auto; } .contentUl li{ } .btnContainer{ height: 30px; margin: 20px auto; } .btnContainer span{ border: 1px solid grey; box-shadow: 0 1px 2px #0f6674; margin: 0 3px; padding: 0 5px; cursor: pointer; } .btnContainer span.active{ border: none; box-shadow: none; color: orangered; font-weight: bold; } </style> </head> <body> <ul class="contentUl" id="contentUl"></ul> <div class="btnContainer"></div> <script> var contentUl=document.querySelector('#contentUl'); var btnContainer=document.querySelector('.btnContainer'); $.get('multiPages.php',function (data) { var content=JSON.parse(data); //获取后台数据 // 定义页码索引 var rows=5; var rowsNum=content.length; var pagesNum=Math.ceil(content.length/rows); var activePageNum=1; //默认加载第一页。 //创建分页索引 $('<span>上一页</span>').appendTo(btnContainer); for (var j=1;j<=pagesNum;j++){ $('<span>'+j+'</span>').appendTo(btnContainer); } $('<span>下一页</span>').appendTo(btnContainer); $('.btnContainer span').eq(1).addClass('active'); // 定义分页内容 function turnPage(activePageNum){ var rowsIndex=rows*activePageNum; if (rowsIndex>rowsNum){ rowsIndex=rowsNum; } //每次生成页面内容前对列表进行清空操作,否则会造成内容累加! $('#contentUl').empty(); //empty()为jQ方法,JS变量无法调用 for (var i=rows*(activePageNum-1);i<rowsIndex;i++){ $('<li>'+content[i]["author"]+':<br>'+content[i]["summary"]+'<li>').appendTo(contentUl); } } turnPage(activePageNum) //定义分页敲击事件 $('.btnContainer span').click(function () { var clickPageNum=$(this).html(); if (clickPageNum=='上一页'){ activePageNum--; if (activePageNum<1){ activePageNum=1; return; } }else if (clickPageNum=='下一页'){ activePageNum++; if (activePageNum>pagesNum){ activePageNum=pagesNum; return; } }else { activePageNum=clickPageNum; } //点击翻页时清除其他兄弟元素的“active”属性。 $('.btnContainer span').eq(activePageNum).addClass('active').siblings().removeClass('active'); turnPage(activePageNum); }); }); </script> </body> </html>
<?php $dbBase=new PDO('mysql:host=localhost;dbname=dbTest;charset=utf8','root',''); $res=$dbBase->query('select * from news where 1'); if($res){ $data=$res->fetchAll(PDO::FETCH_ASSOC); echo json_encode($data); }else{ echo '没有数据!'; } ?>