ajax原理及使用案例

一、什么是ajax?

ajax用来和服务器进行交互,即前端与后端进行交互的桥梁。

二、ajax的特点:

提交少量数据;

异步;

补充:异步和同步【异步:同时分开执行】【同步:按顺序执行】

提高程序的执行效率;

提高用户体验;

减少宽带。

三、ajax的作用:

无刷新页面。

四、ajax原理(代码展示):

   /*创建ajax对象:XMLHttpRequest是一个内置函数,所以ajax对象是new出来的对象;需要做兼容:
     标准浏览器:var xhr = new XMLHttpRequest;
     ie浏览器:var xhr = new ActiveXObject('Microsoft.HMLHTTP')
  */
  var xhr = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject('Microsoft.HMLHTTP');
    /*与服务器建立连接:有三个参数:
    第一个参数:get/post   ajax一般采用get传值,因为get是路径传值,而且传递的数据少,符合ajax传少量值的特点。
    get和post的区别:get:路径传值;传递的数据少;传递的数据用户可见;便于调试;安全度低;
                   post:非路径传值;传递的数据相对get多;传递的数据用户不可见;不便于调试;安全度相对于get高;
    第二个参数:路径;
    第三个参数:布尔值(是否异步:TRUE--异步--默认值)
    */
   xhr.open('GET','1.txt',true);
   //发送请求:
   xhr.send();
   //通过服务器处理数据并返回处理结果
        xhr.onreadystatechange = function(){
            /*判断状态值:
            0:请求还未初始化;
            1:请求已建立,还未发送
            2:请求已发送,还未处理
            3:处理部分请求
            4:请求处理完成
                */
                if(xhr.readyState === 4){
                    /*判断状态码:
                    404:路径错误;
                    200:交易成功;
                    400:服务器语法错误;
                    500:服务器内部错误;
                    */
                    if(xhr.status === 200){
                        //alert(xhr.responseText);
                    oDiv.innerHTML = xhr.responseText;
                    }
                }
        }

文字叙述ajax的工作原理:

通过创建XMLHttpRequest对象;

通过open与服务器建立连接;

通过send将请求发送给后端;

通过onreadystatechange事件监听后端状态;

当readyState返回值的状态是4,并且Status返回码的状态是200时,表示服务器已找到请求的数据并通过回调函数将响应的responseText数据返回给前端,如果返回404,则表示没有找到请求的数据,即路径错误。

五、ajax的缓存问题(以点击指定按钮显示指定数据为例):

ajax.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div{
            width:300px;
            height:100px;
            border:1px solid black;
        }
    </style>
</head>
<body>
    <p><button id = "btn1">认识kinoko</button></p>
    <p><button id = "btn2">了解kinoko</button></p>
    <p><button id = "btn3">熟悉kinoko</button></p>
    <div id = "box"></div>
</body>
</html>
<script src= "ajax.js"></script>
<script>
//获取按钮:
var obtns = document.getElementsByTagName('button');
var oDiv = document.getElementById('box');
for(let i =0 ,len=obtns.length;i<len;i++){
    obtns[i].onclick = function(){
  var xhr = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject('Microsoft.HMLHTTP');
   xhr.open('GET',(i+1)+'.txt?t='+new Date().getTime());//注意此处路径的写法,因为使用let声明变量,不会提升变量,所以i可以直接拿来用;
   //如果用var声明变量,则需要给i重新定义:obtns[i].index = i;此时路径为:(i+1)+'.txt';或者不给i重新定义,路径为
   //this.index+'.txt'.
   xhr.send();
        xhr.onreadystatechange = function(){
                if(xhr.readyState === 4){
                    if(xhr.status === 200){
                    oDiv.innerHTML = xhr.responseText;
                    }
                }
        }
    }
}
</script>

txt文件:

1.txt

你好!
欢迎来到kinoko的世界。
kinoko衷心款待大神哦!

2.txt

kinoko是一个只喝露水的小仙女;
一定要善待她哦!

3.txt

哈哈哈.......
是不是有点喜欢她呢?
只能回答yes!

我们知道ajax的作用是无刷新页面,正常情况只要我们对txt做了改动,在不刷新页面的情况下点击按钮,会自动更新内容。但当我们使用ie浏览器运行以上代码时,会发现更新txt文件时,点击按钮,页面并不会去更新,这个bug就是ajax的缓存问题,要解决这个问题,我们得先知道为什么会存在这个bug,什么原因导致的,当浏览器多次请求同一个文件时,如果路径不发生改变,后面的多次请求就直接从浏览器缓存拿数据,导致了服务器发生更改时,就无法拿到服务器的数据。

究其本质是因为路径是不变的,所以要解决这会bug,我们是不是应该考虑:浏览器每访问一次该文件,让它的路径发生改变。

解决方法:

方法一:在路径后面加一个一直在变的参数

1.url?id=Math.random();

2.url ?id=new Date().getTime();

这个方法会在浏览器产生缓存,用起来并不会很ok

方法二:手动在浏览器清除缓存

这个方法虽然可以解决这个bug,但不推荐使用

方法三:

添加请求头:xhr.setRequestHeader('if-modified-since','0');[比较服务器上最后文件的修改时间,如果时间一样,则直接从浏览器缓存获取数据;如果不一样,则先清除浏览器之前的缓存,再从服务器获取更新后的数据。不会有过多的缓存,推荐使用]写在open和send的中间。

 六、ajax跨域问题:

在说ajax跨域之前先说一下同源策略;

1、同源策略:是浏览器的保护机制,为了保护用户信息的安全;同源指协议、域名、端口号保持一致;

使用ajax请求服务器数据时,要保证协议、域名、端口号和ajax请求的路径完全一致;

因为同源策略,ajax不能跨域;

jsonp是我们用来解决ajax跨域问题的。

2.jsonp:

jsonp工作原理:

动态创建一个script标签,添加到body中;

设置script的src属性,src属性的值是一个接口,即路径,在路径上有一个特殊参数:回调函数;

服务器通过对回调函数的调用,使用参数传递的方式将服务器处理的结果传回客户端。

3.jsonp接口和ajax接口的区别:

jsonp接口有一个特殊的参数--回调函数,ajax没有;

jsonp是路径传值,所以只支持get传递,ajax同时支持get和post;

jsonp返回的是对象,ajax返回的是字符串。

具体以代码展示:

jsonp.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script>
    document.onclick = function(){
        //动态创建script标签:
        var labelScript = document.createElement('script');
        //将script标签加到body中;
        document.body.appendChild(labelScript);
       // alert(labelScript);
       //设置script标签的src属性:
       labelScript.src = "http://localhost/ajax/jsonp/jsonp.php?cb=fn";
    }
    //通过对回调函数的调用,利用参数传递将服务器处理的结果返回客户端。这个函数必须是全局函数。
    function fn(msg){
        alert(msg);//此处输出的是服务器echo出的数据。控制台输出:[object object]
    }
</script>

jsonp.php文件:

<?php
   //接受客户端传递的数据,因为是路径传值,所以只能用get获取:
   $fun = $_GET['cb'];
   //创建一个伪服务器:
   $arr = array('uname'=>'liyabixa');
   //将数组转成json对象:
   $jso = json_encode($arr);
   //通过回调函数将处理后的结果利用参数传递返回给客户端:
   //此处echo出的就是服务器处理后的数据,也就是要返回给客户端的数据。
   echo $fun."(".$jso.")";
?>

 七、案例:

1、   定义一个json文件   加载产品列表

Json文件   

[

         {"pid":"01","pname":"苹果","price":12},

         {"pid":"02","pname":"香蕉","price":23},

         {"pid":"03","pname":"火龙果","price":56}

]

 

通过ajax  获取这些json数据,并将这些产品信息 动态的显示在页面中

product.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        td{
            text-align: center;
        }
    </style>
</head>
<body>
    <table id = "table" border = 1 width = 300 cellspacing = 0>
    </table>
</body>
</html>
<script src = "ajax.js"></script>
<script>
   otable = document.getElementById('table');
   ajaxGet('product.json',function(data){
       //此处data数据就是json文件中的数据,ajax输出json时字符串,所以需要将字符串转成对象;
       var arr = JSON.parse(data);
      // console.log(arr);
      //声明一个容器来存放数据:
       var con = "";
       //遍历数组:
       for(var i = 0,len=arr.length;i<len;i++){
           //console.log(arr[0].pid);
           //模板字符串中嵌入变量,要将变量名写在${}之中。
           //大括号内可以放入任意的JavaScript表达式,可以进行运算,以及引入对象属性。
           con += `<tr><td>${arr[i].pid}</td><td>${arr[i].pname}</td><td>${arr[i].price}</td></tr> `;
       }
       //将容器con中的数据放到table中。
       otable.innerHTML = con;
   }) 
</script>

product.php文件:

[
    {"pid":"01","pname":"苹果","price":12},
    {"pid":"02","pname":"香蕉","price":23},
    {"pid":"03","pname":"火龙果","price":56}
]

 

2、 定义一个json数据:

根据数据  实现 百度智能联想效果

[

     {"pname":"iphone"},

     {"pname":"苹果ipad"},

     {"pname":"hongmi"},

     {"pname":"xiaomi"}

]

文本框 :

idea.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
       li{
           list-style: none;
           color:blue;
       }
    </style>
</head>
<body>
    <input type="text" id = "ipt">
    <ul id = "ul">

    </ul>
</body>
</html>
<script src= '../homework1/ajax.js'></script>
<script>
    //获取页面元素:
var oipt = document.getElementById('ipt');
var oul = document.getElementById('ul');
//给oipt添加键盘弹起事件:
oipt.onkeyup = function(){
    //不清空oul,每触发一次弹起事件,就显示一次内容,所以需要清空oul
    oul.innerHTML = "";
    //通过ajax获取服务器数据:
    ajaxGet('idea.json',function(data){
        var arr = JSON.parse(data);
        var con = "";
        for(var i=0,len=arr.length;i<len;i++){
            //console.log(arr[1].pname);
            //创建li元素并放入ul中
            var oli = document.createElement('li');
            //console.log(oli);
            oli.innerHTML = arr[i].pname;
            if(arr[i].pname.indexOf(oipt.value)!=-1){
                oul.appendChild(oli);
            }
        }
    })
}
</script>

idea.php文件:

[
    {"pname":"iphone"},
    {"pname":"苹果ipad"},
    {"pname":"hongmi"},
    {"pname":"xiaomi"}
]

附件--ajax.js文件:

function ajaxGet(url,callback,data){
    var xhr = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject('Microsoft.HMLHTTP');    
    xhr.open("get",url);
    xhr.send();
    xhr.onreadystatechange = function(){
        if( xhr.status==200&&xhr.readyState==4 ){
            //通过函数调用的方式 将服务器处理的结果通过参数返回
            callback(xhr.responseText);
        }
    }
}

 三、分页

list.html文件:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <link rel="stylesheet" href="main.css" />
        <style>
            .header{
                height: 40px;
                width: 900px;
                margin: 0 auto 50px;
            }
            #box{
                width: 300px;
                height: 30px;
                border: 1px solid black;
                float: left;
                margin-left:500px;
            }
            #box li{
                list-style: none;
                display: inline-block;
                padding: 0 5px;
                float: left;
            }
            #box li.active{
                color: red;
                background-color: green;
            }
            #box ul{
                /* float: left; */
                display: inline-block;
            }
        </style>
    </head>
    <body>                  
        <ul class="shoplist clearfix" id="main">
            <!--<li>
                <img src="img/1.jpg" alt="" />
                <p>小米1</p>
                <p>999</p>
                <button>购买</button>
            </li>-->
        </ul>    
        <div id="box">
            <span id="left">上一页</span>
            <ul id="u">
                <li>1</li>
                <li>2</li>
                <li>3</li>
            </ul>
            <span id="right">下一页</span>
        </div>
    </body>
</html>
<script src="ajax.js"></script>
<script>
/*思路:
1.通过ajax获取json中的数据,因为ajax获取的数据是string,所以需要将字符串转成对象,
*/
//获取页面元素:
var u = document.getElementById('main');
var uu = document.getElementById('u');
var index = 1;
var pagenum=4;
//console.log(u);
page();
function page(){
    ajaxGet('data.json',function(data){
     //将字符串转成对象;
     var arr = JSON.parse(data);
    console.log(arr);
     //声明一个空容器来存放数据:
     var con = "";
     //遍历数组:
     //遍历数组的同时要考虑到一行放几张图片:
     for(var i =(index-1)*4;i<index*pagenum;i++){
         //判断最后一排的数量,此处不判断,最后一排不会显示,因为一共4页,一页4张,所有第五页的就不会显示;
         if(i<17){
         //用字符串模板来创建li标签,在创建li标签的同时将json中的数据放到li标签中:
         con += `<li>
                <img src="img/${arr[i].src}"  alt="" />
                <p>${arr[i].name}</p>
                <p>${arr[i].price}</p>
                <button>购买</button>
            </li>`
         }
     }
     //将li放到ul中:
    main.innerHTML = con;
    //确定页数:数组的长度/一页的数
    var total = Math.ceil(arr.length/pagenum);
    var page = "";
    for(var i = 1; i<total-1;i++){
        page += `<li>${i}</li>`
    }
    uu.innerHTML=page;
    //当前页码index高亮显示:
    uu.children[index-1].className="active";
})
}
//添加点击事件:
//点击页码:所有的li都需要添加点击事件,所以通过事件委托给li添加点击事件:
uu.onclick = function(e){
    //做事件兼容:
    var e = e || event;
    //做事件源兼容:
    var target = e.target ||e.srcElement;
    if(target.tagName == 'LI'){
        index = target.innerHTML;//用tagName来获取标签,返回值是大写的。
        page();
    }
}
//上一页:
left.onclick = function(){
    index--;
    if(index==0){
        index=1;        
    }else{
        page();
    }
}
//下一页:
right.onclick = function(){
    index++;
    if(index==6){
        index = 5;
    }else{
        page();
    }
}
</script>

附件1--ajax.js

// url :请求路径
// callback :  该参数是一个函数,回调函数
// data :  接口的参数
function ajaxGet(url,callback,data){
    var ajax = null;
    if( window.XMLHttpRequest ){
        ajax = new XMLHttpRequest();
    }else{
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    if(arguments.length == 3){//表示传递的参数有三个  
        url = url + "?" + data;
    }
    ajax.open("GET",url,true);
    ajax.onreadystatechange = function(){
        if( ajax.readyState == 4 && ajax.status == 200 ){
            if(callback){
                callback(ajax.responseText);//通过函数的调用将服务器处理的结果以参数形式传递给前端
            }     
        }
    }
    ajax.send(); 
}

function ajaxPost(url,callback,data){
    var ajax = null;
    if( window.XMLHttpRequest ){
        ajax = new XMLHttpRequest();
    }else{
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    
    ajax.open("POST",url);
    
    //设置请求头:
    ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    
    ajax.onreadystatechange = function(){
        if(ajax.readyState == 4 && ajax.status == 200){
            callback(ajax.responseText);
        }
    }    
    ajax.send(data);//向服务器端发送数据 用户名
}

附件2--data.json:

[
    {
        "id" : "shop01",
        "name" : "小米1",
        "src" : "9.jpg",
        "price" : "999"
    },
    {
        "id" : "shop02",
        "name" : "小米2",
        "src" : "2.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米3",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop04",
        "name" : "小米4",
        "src" : "4.jpg",
        "price" : "999"
    },
    {
        "id" : "shop05",
        "name" : "小米5",
        "src" : "5.jpg",
        "price" : "999"
    },
    {
        "id" : "shop06",
        "name" : "小米6",
        "src" : "6.jpg",
        "price" : "999"
    },
    {
        "id" : "shop07",
        "name" : "小米7",
        "src" : "7.jpg",
        "price" : "999"
    },
    {
        "id" : "shop08",
        "name" : "小米8",
        "src" : "8.jpg",
        "price" : "999"
    },
    {
        "id" : "shop09",
        "name" : "小米9",
        "src" : "9.jpg",
        "price" : "999"
    },
    {
        "id" : "shop10",
        "name" : "小米10",
        "src" : "10.jpg",
        "price" : "999"
    },
    {
        "id" : "shop01",
        "name" : "小米11",
        "src" : "9.jpg",
        "price" : "999"
    },
    {
        "id" : "shop02",
        "name" : "小米12",
        "src" : "2.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米13",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop02",
        "name" : "小米14",
        "src" : "2.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米15",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop02",
        "name" : "小米16",
        "src" : "2.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    },
    {
        "id" : "shop03",
        "name" : "小米17",
        "src" : "3.jpg",
        "price" : "999"
    }
    
]
    

附件3--main.css:

*{
    border: 0;
    padding: 0;
    margin: 0;
}

ul,li,ol{
    list-style-type: none;
}

/* ie 6/7 */
.clearfix{
    *zoom : 1;
    *height: 1px;
}
/* IE8+ */
.clearfix:after{
    content: "";
    height: 0;
    clear: both;
    display: block;
    visibility: hidden;
}

.nav{
    width: 900px;
    border: 1px solid red;
    
    margin: 0 auto;
}

.nav > span{
    display: inline-block;
    float: left;
    width: 100px;
    height: 40px;
    text-align: center;
    line-height: 40px;
    padding: 10px 0;
    border-right: 1px solid red;
    cursor: pointer;
}
.nav > span.cur{
    color: red;
}
.shoplist{
    width: 900px;
    display: block;
    margin: 50px auto 0;

}
.shoplist > li{
    width: 200px;
    /*height: 200px;*/
    border: 1px solid #d1d1d1;
    text-align: center;
    float: left;
    margin-right: 10px;
    margin-bottom: 10px;
}
.shoplist > li button{
    font-size: 24px;
    margin-top: 10px;
    cursor: pointer;
    border: 1px solid #000;
}
.shoplist > li img{
    height: 150px;
    display: inline-block;
}
.shoplist > li p{
    width: 100%;
    height: 20px;
    margin-top: 5px;
}

 

posted @ 2019-01-23 17:28  kinoko-木子  阅读(347)  评论(0编辑  收藏  举报