Ajax 之 (一)无刷新分页、xml信息的接收和处理、对缓存的处理

Ajax

什么是ajax

Ajax: asynchronous javascript and xml (异步js和xml)
其是可以与服务器进行(异步/同步)交互的技术之一。
ajax的语言载体是javascript。
最大特点:页面不刷新
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

ajax出现的历史

1999年,微软公司发布IE5浏览器的时候嵌入的一种技术。起初名字是XMLHttp。
直到2005年,google公司发布了一个邮箱产品gmail,内部有使用ajax技术,该事情引起人们对ajax的注意,也使得一蹶不振的javascript语言从此被人们重视起来。

ajax技术是许多旧技术的集合

xhtml、css、javascript、xml、xmlhttprequest对象(ajax对象)
其中XMLHttpRuquest是ajax的官方的名称。

ajax使用

创建ajax对象

主流(火狐、google、苹果safari、opera)浏览器方式

包括IE7以上版本的浏览器
var xhr = new XMLHttpRequest();

IE(6/7/8)方式

var xhr = new ActiveXObject(“Microsoft.XMLHTTP”);  //最原始方式
var xhr = new ActiveXObject("Msxml2.XMLHTTP");    //升级
var xhr = new ActiveXObject("Msxml2.XMLHTTP.3.0");  //升级
var xhr = new ActiveXObject("Msxml2.XMLHTTP.5.0");  //升级
var xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");  //最高版本方式
<script type='text/javascript'>
    //创建ajax对象
    if(typeof XMLHttpRequest != 'undefined'){
        //主流方式
        var xhr = new XMLHttpRequest();
    }else{
        //IE(6/7/8)方式
        var xhr = new ActiveXObject("Microsoft.XMLHTTP");  //最原始方式
        var xhr = new ActiveXObject("Msxml2.XMLHTTP");   //升级
        var xhr = new ActiveXObject("Msxml2.XMLHTTP.3.0");  //升级
        var xhr = new ActiveXObject("Msxml2.XMLHTTP.5.0");  //升级
        var xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");  //最高版本方式
    }
    alert(xhr);
</script>

发起对服务器的请求

这里写图片描述

<script type='text/javascript'>
    //ajax 发起请求
    //1、创建对象
    var xhr = new XMLHttpRequest();

    //2、创建一个新的http请求(打开浏览器,输入请求地址)
    //xhr.open(请求方式get/post等等,请求地址[,异步同步请求]);
    xhr.open('get','../1.php');

    //3、发送请求
    //xhr.send(post请求数据 / get请求设置null);
    xhr.send(null);
</script>

这里写图片描述

接收服务器返回信息

ajax可以接收什么信息?
答:浏览器可以接收的信息ajax都可以接收,例如字符串、html标签、css样式内容、xml内容、json内容等等。

<html>
<head>
<meta charset='utf-8' />
<script type='text/javascript'>

    function f1(){
        var xhr = new XMLHttpRequest();

        //设置事件onreadystatechange 感知ajax状态变化
        xhr.onreadystatechange = function(){
            //readyState 变量表示ajax对象状态,其值见下文
            console.log(xhr.readyState);
            if(xhr.readyState==4)
                //xhr.responseText 可返回页面echo出的内容
                alert(xhr.responseText);
        }

        xhr.open('get','../1.php');
        xhr.send(null);
    }
</script>
</head>
<body>
<input type='button' value='点击' onclick='f1()'>
</body>
</html>

readyState 为只读变量,状态用长度为4的整型表示,定义如下:

代表意义
0 (未初始化)对象已建立,但是尚未初始化(尚未调用open方法)
1 (初始化)对象已建立,尚未调用send方法
2 (发送数据)send方法已调用,但是当前的状态及http头未知
3 (数据传送中)已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误
4 (完成)数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据

常用属性

属性代表意义
onreadystatechange*指定当readyState属性改变时的事件处理句柄。只写
readyState返回当前请求的状态,只读.
responseBody将回应信息正文以unsigned byte数组形式返回.只读
responseStream以Ado Stream对象的形式返回响应信息。只读
responseText将响应信息作为字符串返回.只读
responseXML将响应信息格式化为Xml Document对象并返回,只读
status返回当前请求的http状态码.只读
statusText返回当前请求的响应行状态,只读

常用方法

方法代表意义
abort取消当前请求
getAllResponseHeaders获取响应的所有http头
getResponseHeader从响应信息中获取指定的http头
open创建一个新的http请求,并指定此请求的方法、URL以及验证信息(用户名/密码)
send发送请求到http服务器并接收回应
setRequestHeader单独指定请求的某个http头

get和post方式的ajax请求

ajax对象.open(get/post, 请求地址);

两者的不同

  1. 给服务器传递数据量,get最多是2k
     post原则没有限制,php.ini对其限制为8M
  2. 安全方面,post传递数据较安全
  3. 传递数据的形式不一样
    get方式在url地址后边以请求字符串形式传递参数
    http://网址/index.php?name=tom&age=23&addr=beijing

    post方式是把form表单的数据给请求出来以xml形式传递给服务器

ajax之get方式请求

  1. 在url地址后边以请求字符串(传递的get参数信息)形式传递数据。
  2. 对中文、=、&等特殊符号处理
    =、&符号在浏览器里边会与请求字符串的关键符号有混淆,避免歧义产生需要对其进行编码.
    这里写图片描述

在浏览器的地址栏里边传递一些特殊符号信息,会被误解,例如 & = 空格 中文。
在php里边可以函数函数 urlencode()/urldecode() 对特殊符号进行编码、反编码处理
(url_encode()可以把中文转变为浏览器可以识别的信息。转变之后的信息具体为%号后接两个十六进制数)
在javascript里边可以通过 encodeURIComponent () 对特殊符号等信息进行编码。

经过以上 加粗 函数编码的内容在服务器端可以正常接收,不需要反编码。

这里写图片描述

ajax之post方式请求

  1. 给服务器传递数据需要调用send(请求字符串数据)方法
  2. 调用方法setRequestHeader()把传递的数据组织为xml格式(模仿form表单给服务器传递数据)
  3. 传递的中文信息无需编码,特殊符号像 &、=等 需要编码
  4. 该方式请求的同时也可以传递get参数信息,同样使用$_GET接收该信息

这里写图片描述

这里写图片描述

<html>
<head>
<meta charset='utf-8' />
<script type='text/javascript'>

    function f1(){
        //ajax 负责抓取用户名信息,传递给服务器进行校验

        //获取用户名信息
        var un = document.getElementsByTagName('input')[0].value;
        un = encodeURIComponent(un);

        var xhr = new XMLHttpRequest();     
        xhr.onreadystatechange = function(){            
            if(xhr.readyState==4)
                alert(xhr.responseText);
        }

        xhr.open('post','../1.php');
        //post模仿form表单把数据传递给服务器
        //form表单把数据组织为“xml格式”传递给服务器
        //把传递的数据组织为请求字符串

        //以下方法设置header头信息,作用把传递的数据组织为xml格式
        //(要在open()方法执行之后设置)
        xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
        var info = 'name='+un+'&age=20';
        xhr.send(info);
    }
</script>
</head>
<body>
<input type='text' value='' name='username'>
<input type='button' value='提交' onclick='f1()'>
</body>
</html>

这里写图片描述

同步、异步

ajax是可以与服务器进行(异步或同步)交互的技术之一。
异步:同一个时间点允许执行多个进程。
同步:同一个时间点只允许执行一个进程。
ajax对象.open(请求方式,请求地址,同步false/[异步true]);

这里写图片描述

<script type='text/javascript'>
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function(){
        if(xhr.readyState==4){
            document.body.innerHTML += xhr.responseText;
            //alert(xhr.responseText);
        }
    }
    //true 异步   false 同步
    xhr.open('get','../1.php',true);
    //xhr.open('get','../1.php',false);
    xhr.send(null);
</script>

什么时候使用同步请求

ajax绝大多数情况下进行异步请求,但是有的时候也要使用“同步请求”(其不能被取代)。例如页面有两部分内容,一前一后,ajax请求和正常的html内容输出,如果html的输出内容包括ajax请求的内容,就需要使得ajax请求完成了再进行html内容的输出,这样就要设置两者一前一后调用(而非同时调用),此时要使用同步请求。

ajax无刷新分页效果

这里写图片描述

http://网址/data.php?page=1
http://网址/data.php?page=2
http://网址/data.php?page=3
.....

传统分页效果,获得每页信息的时候全部页面都需要刷新。

无刷新分页的必要性

如果我们通过“传统方式”实现上图的商品评论分页效果,每次分页的时候就会使得头部、左侧、底部等已经显示的信息重新从服务器获得出来,这样对带宽、服务器资源、用户等待时间都有额外的损耗。如果使用ajax无刷新分页,每次就只从服务器获得“商品评论区域”信息即可,对各方面资源的使用就有相应节省。因此ajax无刷新分页效果有其存在必要性。

具体实现

记录总条数
每页显示条数
总页数:向上取整(总条数/每页显示条数)
limit 偏移量((当前页码-1)*每页条数),长度;

http://网址/data.php?page=1 (limit 0,7)
http://网址/data.php?page=2 (limit 7,7)
http://网址/data.php?page=3 (limit 14,7)

ajax对象.open(‘get’,地址http://网址/data.php?page=2);
利用ajax无刷新方式获得第2页信息

制作传统分页效果

page.class.php

<?php
    class Page {
        private $total; //数据表中总记录数
        private $listRows; //每页显示行数
        private $limit;
        private $uri;
        private $pageNum; //页数
        private $config=array('header'=>"个记录", "prev"=>"上一页", "next"=>"下一页", "first"=>"首 页", "last"=>"尾 页");
        private $listNum=8;
        /*
         * $total 
         * $listRows
         */
        public function __construct($total, $listRows=10, $pa=""){
            $this->total=$total;
            $this->listRows=$listRows;
            $this->uri=$this->getUri($pa);
            $this->page=!empty($_GET["page"]) ? $_GET["page"] : 1;
            $this->pageNum=ceil($this->total/$this->listRows);
            $this->limit=$this->setLimit();
        }

        private function setLimit(){
            return "Limit ".($this->page-1)*$this->listRows.", {$this->listRows}";
        }

        private function getUri($pa){
            $url=$_SERVER["REQUEST_URI"].(strpos($_SERVER["REQUEST_URI"], '?')?'':"?").$pa;
            $parse=parse_url($url);



            if(isset($parse["query"])){
                parse_str($parse['query'],$params);
                unset($params["page"]);
                $url=$parse['path'].'?'.http_build_query($params);

            }

            return $url;
        }

        function __get($args){
            if($args=="limit")
                return $this->limit;
            else
                return null;
        }

        private function start(){
            if($this->total==0)
                return 0;
            else
                return ($this->page-1)*$this->listRows+1;
        }

        private function end(){
            return min($this->page*$this->listRows,$this->total);
        }

        private function first(){
            $html = "";
            if($this->page==1)
                $html.='';
            else
                $html.="&nbsp;&nbsp;<a href='{$this->uri}&page=1'>{$this->config["first"]}</a>&nbsp;&nbsp;";

            return $html;
        }

        private function prev(){
            $html = "";
            if($this->page==1)
                $html.='';
            else
                $html.="&nbsp;&nbsp;<a href='{$this->uri}&page=".($this->page-1)."'>{$this->config["prev"]}</a>&nbsp;&nbsp;";

            return $html;
        }

        private function pageList(){
            $linkPage="";

            $inum=floor($this->listNum/2);

            for($i=$inum; $i>=1; $i--){
                $page=$this->page-$i;

                if($page<1)
                    continue;

                $linkPage.="&nbsp;<a href='{$this->uri}&page={$page}'>{$page}</a>&nbsp;";

            }

            $linkPage.="&nbsp;{$this->page}&nbsp;";


            for($i=1; $i<=$inum; $i++){
                $page=$this->page+$i;
                if($page<=$this->pageNum)
                    $linkPage.="&nbsp;<a href='{$this->uri}&page={$page}'>{$page}</a>&nbsp;";
                else
                    break;
            }

            return $linkPage;
        }

        private function next(){
            $html = "";
            if($this->page==$this->pageNum)
                $html.='';
            else
                $html.="&nbsp;&nbsp;<a href='{$this->uri}&page=".($this->page+1)."'>{$this->config["next"]}</a>&nbsp;&nbsp;";

            return $html;
        }

        private function last(){
            $html = "";
            if($this->page==$this->pageNum)
                $html.='';
            else
                $html.="&nbsp;&nbsp;<a href='{$this->uri}&page=".($this->pageNum)."'>{$this->config["last"]}</a>&nbsp;&nbsp;";

            return $html;
        }

        private function goPage(){
            return '&nbsp;&nbsp;<input type="text" onkeydown="javascript:if(event.keyCode==13){var page=(this.value>'.$this->pageNum.')?'.$this->pageNum.':this.value;location=\''.$this->uri.'&page=\'+page+\'\'}" value="'.$this->page.'" style="width:25px"><input type="button" value="GO" onclick="javascript:var page=(this.previousSibling.value>'.$this->pageNum.')?'.$this->pageNum.':this.previousSibling.value;location=\''.$this->uri.'&page=\'+page+\'\'">&nbsp;&nbsp;';
        }
        function fpage($display=array(0,1,2,3,4,5,6,7,8)){
            $html[0]="&nbsp;&nbsp;共有<b>{$this->total}</b>{$this->config["header"]}&nbsp;&nbsp;";
            $html[1]="&nbsp;&nbsp;每页显示<b>".($this->end()-$this->start()+1)."</b>条,本页<b>{$this->start()}-{$this->end()}</b>条&nbsp;&nbsp;";
            $html[2]="&nbsp;&nbsp;<b>{$this->page}/{$this->pageNum}</b>页&nbsp;&nbsp;";

            $html[3]=$this->first();
            $html[4]=$this->prev();
            $html[5]=$this->pageList();
            $html[6]=$this->next();
            $html[7]=$this->last();
            $html[8]=$this->goPage();
            $fpage='';
            foreach($display as $index){
                $fpage.=$html[$index];
            }

            return $fpage;

        }


    }
<?php
//传统分页效果实现
//连接数据库,获得数据,做分页显示

header("content-type:text/html;charset=utf-8");
$link = mysql_connect('localhost','root','123456');
mysql_select_db('shop', $link);
mysql_query('set names utf8');

echo <<<eof
    <style type="text/css">
        table {width:700px; border:1px solid black; margin:auto; border-collapse:collapse;}
        td {border:1px solid black; }
    </style>
    <table>
        <tr style='font-weight:bold'><td>序号</td><td>名称</td><td>价格</td><td>数量</td><td>重量</td></tr>
eof;

//① 引入分页类
include "./page.class.php";

//② 获得总条数、每页显示条数
$sql = "select * from sw_goods";
$qry = mysql_query($sql);
$total = mysql_num_rows($qry); //总条数
$per = 7;//每页条数

//③ 实例化分页类对象
$page = new Page($total, $per);

//④ 设置sql语句获得每页信息
//$page->limit:分页类会根据当前页码参数自动把 "limit 偏移量,长度" 信息给拼装好
$sql3 = "select * from sw_goods order by goods_id ".$page->limit;
$qry3 = mysql_query($sql3);

//⑤ 获得页码列表信息
$page_list = $page -> fpage(array(3,4,5,6,7,8));

$page_num = isset($_GET['page'])?$_GET['page']:1;
$num = ($page_num-1)*$per+1;

while($rst3 = mysql_fetch_assoc($qry3)){
    printf("<tr>");
    printf("<td>%d</td>",$num);
    printf("<td>%s</td>",$rst3['goods_name']);
    printf("<td>%s</td>",$rst3['goods_price']);
    printf("<td>%d</td>",$rst3['goods_number']);
    printf("<td>%d</td>",$rst3['goods_weight']);
    printf("</tr>");
    $num++;
}
printf("<tr><td colspan='5'>%s</td></tr>",$page_list);
echo "</table>";

制作ajax无刷新分页效果

这里写图片描述

这里写图片描述

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
    <head>
        <title>新建网页</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="description" content="" />
        <meta name="keywords" content="" />

        <script type="text/javascript">
        //函数封装,实现ajax获取分页信息
        function showpage(url){
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState==4){
                    document.getElementById('result').innerHTML = xhr.responseText;
                }
            }
            xhr.open('get',url);
            xhr.send(null);
        }
        window.onload = function(){
            showpage('./data.php');
        }
        </script>
        <style type="text/css">
        h2,div {width:700px; margin:auto;}
        h2 {text-align:center;}
        </style>
    </head>
    <body>
        <h2>ajax无刷新分页</h2>
        <div id="result"></div>
    </body>
</html>
<script type="text/javascript">
<!--
    document.write(new Date()+"<br />");
    document.write(new Date()+"<br />");
    document.write(new Date()+"<br />");
    document.write(new Date()+"<br />");
//-->
</script>

ajax对xml信息的接收和处理

ajax负责请求xml和接收xml信息,dom负责处理xml信息
dom:
  php里边,dom是php与xml(html)之间的沟通桥梁
  javascript里边,dom是javascript与html(xml)之间沟通桥梁
这里写图片描述

08.xml

<?xml version="1.0" encoding="utf-8" ?>
<students>
    <student>
        <name>刘飞</name>
        <age>20</age>
        <addr>辽宁</addr>
    </student>
    <student>
        <name>苏建</name>
        <age>21</age>
        <addr>河北</addr>
    </student>
    <student>
        <name>王阳</name>
        <age>18</age>
        <addr>山东</addr>
    </student>
</students>
<script type="text/javascript">
        function f1(){
            //ajax请求xml信息回来
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState==4){
                    //alert(xhr.responseText); //以字符串格式返回xml信息
                    //alert(xhr.responseXML); //[object XMLDocument]以xmldocument对象格式返回xml信息
                    var xmldom = xhr.responseXML;
                    //console.log(xmldom.firstChild);//<students>
                    //console.log(xmldom.firstChild.childNodes);//NodeList[<TextNode textContent="\n ">, student, <TextNode textContent="\n ">, student, <TextNode textContent="\n ">, student, <TextNode textContent="\n">]

                    //文档对象.getElementsByTagName(tag名称);
                    //元素节点.getElementsByTagName(tag名称);
                    var std = xmldom.getElementsByTagName('student');
                    //console.log(std);//HTMLCollection[student, student, student]
                    //console.log(std[0]);//<student>元素节点对象
                    //for(var k in std[0]){
                    //    console.log(k);
                    //}

                    var s = "";
                    for(var i=0; i<std.length; i++){
                        var nm = std[i].getElementsByTagName('name')[0].innerHTML;
                        var age = std[i].getElementsByTagName('age')[0].firstChild.wholeText;
                        var addr = std[i].getElementsByTagName('addr')[0].innerHTML;

                        s += "名称:"+nm+"--年龄:"+age+"--地址:"+addr+"<br />";
                    }
                    document.body.innerHTML += s;
                }
            }
            xhr.open('get','./08.xml');
            xhr.send(null);
        }
        </script>

这里写图片描述

这里写图片描述

ajax对缓存的处理

缓存:
一次请求需要从服务器获得许多 css、img、js 等相关的文件,如果每次请求都把相关的资源文件加载一次,对 带宽、服务器资源、用户等待时间 都有严重的损耗,浏览器有做优化处理,其把css、img、js在第一次请求成功后就在本地保留一个缓存备份,后续的每次请求就在本身获得相关的缓存资源文件及可以了,可以明显地加快用户的访问速度。
css、img、js等文件可以缓存,但是动态程序文件例如php文件不能缓存,即时缓存我们也不要其缓存效果。

缓存解决:
① 确保每次的请求地址信息是唯一的
② 在php代码里边设置header头,禁止浏览器缓存当前页面

09-cache.html

<script type="text/javascript">
        //ajax发起请求
        function f1(){
            //创建ajax对象,对象调用成员实现对服务器的请求
            //① 创建对象
            var xhr = new XMLHttpRequest();

            //② 创建一个新的http请求(打开浏览器,输入请求地址)
            //xhr.open(请求方式get/post,请求地址[,异步同步请求]);
            //xhr.open("get",'./09.php?'+Math.random());//设置随机数,避免缓存效果
            xhr.open("get",'./09.php');

            //③ 发送请求
            //xhr.send(post请求数据 / get请求设置null);
            xhr.send(null);
        }
        </script>

09.php

<?php

//以下三行,禁止浏览器缓存页面
header("Cache-Control:no-cache");
header("Pragma:no-cache");
header("Expires:-1");

$fp = fopen('./09.txt','a'); //打开文件
fwrite($fp,'computer\n');  //给文件写内容
fclose($fp);//关闭文件

echo "haha";

thinkphp框架使用ajax

ajax对象.open(‘get/post’, 绝对路径地址);
ajax对象.open(‘get/post’, /shop/index.php/Home/User/checkname);

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值