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{
- width: 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 '没有数据!';
- }
- ?>