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; }

浙公网安备 33010602011771号