基本使用
发送请求基本五步
Ajax是在不重新加载整个网页的情况下,与服务器交换数据并更新部门网页的方法
使用Ajax的五步:
1. 创建一个异步对象
2. 设置请求方式和请求地址
3. 发送请求
4. 监听状态的变化
5. 处理返回的结果
var btn = document.getElementsByTagName("button")[0];
btn.onclick = function () {
// 1、创建一个异步对象
var xmlHttp = new XMLHttpRequest();
// 2、设置请求方式和请求地址
// 通过w3c文档得知,使用open方法,可以设置请求方式和请求地址
// open方法有三个参数
// method:请求的类型;GET 或 POST
// url:文件在服务器上的位置
// async:true(异步)或 false(同步
// Ajax就是为了异步请求,所以永远传true
xmlHttp.open("GET","demo01.php",true);
// 3、发送请求
// 通过调用send()方法来发送请求
xmlHttp.send();
// 4、监听状态的变化
// 只要状态一发生变化,就会调用回调函数
xmlHttp.onreadystatechange = function () {
// 因为Ajax状态有很多种,所以这时候判断一下
/*
通过readyState方法来获取到请求时的状态
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
*/
if (xmlHttp.readyState === 4) {
// 5、处理返回的结果
console.log("接收到Ajax的请求");
}
}
}
因为Ajax状态有很多种,所以要进行判断,只有当readeState == 4的时候,再才打印,但是这时候就算是我们请求的地址是错误的,我们也会得到第四步,这时候也会收到接收到Ajax的请求,所以还要通过一次判断来判断他是否请求成功
请求不管是否成功都会返回状态码,通过status方法来获取状态码,但是请求成功的状态码都是大于等于200并且小于300的,而且这时候还有一个特殊情况304,这有这几种情况是请求成功的,所以再加一层判断
if (xmlHttp.readyState === 4) {
if(xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status === 304){
// 5.处理返回的结果
console.log("接收到服务器返回的数据");
}else{
console.log("没有接收到服务器返回的数据");
}
}
接收PHP返回的文件
- 当我们发送请求后,我们的服务器会通过PHP来返回数据,这时候数据就是PHP中echo的数据,而获取到echo的数据有以下两种方式:
- responseText 获取字符串形式的响应数据
- responseXML 获取 XML 数据形式的响应数据
var btn = document.getElementsByTagName("button")[0];
btn.onclick = function () {
var xmlBtn = new XMLHttpRequest();
xmlBtn.open("GET", "demo02.php", true);
xmlBtn.send();
xmlBtn.onreadystatechange = function () {
if (xmlBtn.readyState === 4) {
if (xmlBtn.status >= 200 && xmlBtn.status < 300 || xmlBtn.status == 304) {
// 获取到php的echo的字符信息
alert(xmlBtn.responseText);//demo02返回数据
} else {
alert("数据请求失败")
}
}
}
}
封装请求方法
// type是请求类型,URL是路径,obj是传递过来的对象,timeout是请求时间,success是成功时的回调函数,error是失败时的回调函数
function Ajax_ASK(type ,URL ,obj , timeout,success ,error) {
// 通过自定义的方法objToStr()方法将传递过来的obj变成服务器认识的字符串
var val = objToStr(obj);
// 创建异步对象
var xml = new XMLHttpRequest;
if (type == "GET") {
// 选择传递方法
xml.open(type ,URL + "?" + val,true);
// 发送请求
xml.send();
} else {
// 选择传递方法
xml.open(type ,URL,true);
// 注意点: 以下代码必须放到open和send之间
xmlBtn.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// 发送请求,传递参数
xml.send(val);
}
// 设置回调函数
xml.onreadystatechange = function () {
if (xml.readyState == 4) {
// 只要readyState == 4,就代表服务器接收到了请求,就直接关闭定时器
clearInterval(timer);
if (xml.status >= 200 && xml.status < 300 || xml.status == 304) {
// 要是成功了则调用传进来的函数success()
success(xml)
} else {
// 要是失败了则调用传进来的函数error()
error(xml);
}
}
}
// 先判断是否有timeout参数,要是有才执行
if (timeout) {
// 创建一个定时器
timer = setInterval(() => {
// 时间一到就中断请求
xml.abort();
// 请求一中断就删除定时器
clearInterval(timer);
}, timeout);
}
}
// 定义objToStr方法
function objToStr(obj) {
// 先将时间添加到对象的最下面
obj.t = new Date().getTime();
var str = [];
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const elem = obj[key];
//通过调用encodeURIComponent方法,防止key和value出现中文
str.push(encodeURIComponent(key) + "=" + encodeURIComponent(elem));
}
}
// join方法可以将数组变成字符串,并且将元素之间用&来连接
return str.join("&");
}
可以和jQuery官方的Ajax一样的方法完善
// 这时候只需要传递一个对象,对象里包含以下元素,就可以无序的传参了
// type是请求类型,URL是路径,data是传递过来的对象,timeout是请求时间,success是成功时的回调函数,error是失败时的回调函数
function Ajax_ASK(option) {
// 通过自定义的方法objToStr()方法将传递过来的data变成服务器认识的字符串
var str = objToStr(option.data);
// 创建异步对象
var xml = new XMLHttpRequest();
var timer;
// 将type类型转换成小写,这样无论转换的是大写还是小写都是可以判断的
if (option.type.toLowerCase() === "get") {
// 选择传递方法
xml.open(option.type ,option.url + "?" + str,true);
// 发送请求
xml.send();
} else {
// 选择传递方法
xml.open(option.type ,option.url,true);
// 注意点: 以下代码必须放到open和send之间
xml.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// 发送请求,传递参数
xml.send(str);
}
// 设置回调函数
xml.onreadystatechange = function () {
if (xml.readyState == 4) {
// 只要readyState == 4,就代表服务器接收到了请求,就直接关闭定时器
clearInterval(timer);
if (xml.status >= 200 && xml.status < 300 || xml.status == 304) {
// 要是成功了则调用传进来的函数success()
option.success(xml)
} else {
// 要是失败了则调用传进来的函数error()
option.error(xml);
}
}
}
// 先判断是否有timeout参数,要是有才执行
if (option.timeout) {
// 创建一个定时器
timer = setInterval(function() {
// 时间一到就中断请求
xml.abort();
// 请求一中断就删除定时器
clearInterval(timer);
}, option.timeout);
}
}
// 定义objToStr方法
function objToStr(data) {
data = data || {};
// 先将时间添加到对象的最下面
data.t = new Date().getTime();
var str = [];
for (var key in data) {
//通过调用encodeURIComponent方法,防止key和value出现中文
str.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
}
// join方法可以将数组变成字符串,并且将元素之间用&来连接
return str.join("&");
}
Ajax与前端的交互
当前端与后端交互的时候,一般返回的都是XML或者是json文件,并不会返回字符串文件。
XML:
在PHP中可以通过file_get_contents方法来读取到文件路径并且录入到PHP中去,但是要是文件中有中文就会报错,所以要在PHP文件的顶部加上一句
// 执行结果中有中文, 必须在php文件顶部设置
header("content-type:text/html; charset=utf-8");
要是读取的文件是XML数据,并且要返回XML数据,也要在PHP文件顶部加上一段代码
// 如果PHP中需要返回XML数据, 也必须在PHP文件顶部设置
header("content-type:text/xml; charset=utf-8");
echo file_get_contents("info.xml");
所以成了
<?php
// 执行结果中有中文, 必须在php文件顶部设置
//header("content-type:text/html; charset=utf-8");
// 如果PHP中需要返回XML数据, 也必须在PHP文件顶部设置
header("content-type:text/xml; charset=utf-8");
echo file_get_contents("info.xml");
?>
而读取XML的文件也不是使用responseText,而是使用responseXML,它会返回一个document,这个document就是编辑的xml文档里面的内容
再通过getElementsByTagName将自己定义的XML里面的内容读取出来
ajax({
type:"get",
url:"11-ajax-xml.php",
success: function (xhr) {
// console.log(xhr.responseXML);
// console.log(document);
var res = xhr.responseXML;
console.log(res.getElementsByTagName("name")[0].innerHTML);
console.log(res.getElementsByTagName("age")[0].innerHTML);
},
error: function (xhr) {
console.log(xhr.status);
}
})
JSON:
JSON就是一个被字符串嵌套的对象
// JSON和对象的辨别
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
// JSON 和 JS 对象互转
// 要实现从JSON字符串转换为JS对象,使用 JSON.parse() 方法:
var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}
// 要实现从JS对象转换为JSON字符串,使用 JSON.stringify() 方法:
var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'
一般都直接使用txt文件来书写JSON,因为txt文件默认都是字符串
txt文件内容:
{
"name":"ljy",
"age":"18"
}
PHP内容:
<?php
echo file_get_contents("demo07JSONWenJian.txt");
JS内容:
var btn = document.querySelector("button");
btn.onclick = function (ev1) {
Ajax_ASK({
url:"demo07.php",
type:"get",
success:function (xhr) {
// console.log(xhr.responseText);
var str = xhr.responseText;
/*
在低版本的IE中, 不可以使用原生的JSON.parse方法, 但是可以使用json2.js这个框架来兼容
*/
var obj = JSON.parse(str);
console.log(obj);
console.log(obj.name);
console.log(obj.age);
},
error: function (xhr) {
console.log(xhr.status);
}
})
}
会话跟踪
当我们在一个页面停留的时候,在刷新这个页面的时候我们要是想要实现依然停留在某个文本的第几页,而不是从头还是,就有两种技术,一种是Cookie,一种是Hash。
Cookie
Cookie:会话跟踪,将网页中的数据保存到浏览器中
console.log(document.cookie);//
// Cookie默认不会保存数据
Cookie保存的值是可以在浏览器开发工具Application中查看
// 要是想要保存Cookie数据,则需要按照"key = value;"这种格式来保存
document.cookie = "age = 18;";
console.log(document.cookie);//age=18
Cookie的生命周期:
在默认的情况下,Cookie的生命周期是一次会话(浏览器关闭为一次会话结束)
如果通过expires=设置了过期时间, 并且过期时间没有过期, 那么下次打开浏览器还是存在
如果通过expires=设置了过期时间, 并且过期时间已经过期了,那么会立即删除保存的数据
var date = new Date();
date.setDate(date.getDate() - 1);
document.cookie = "age=33;expires="+date.toGMTString()+";";
注意:
- Cookie一次只能保存一条,要是想要保存多条cookie就要分多次保存
- Cookie有大小和个数的限制
个数限制: 20~50
大小限制: 4KB左右 - 访问问题:
- 如果在同一个浏览器中, 默认情况下下一级路径就可以访问
- 如果在同一个浏览器中, 想让上一级目录也能访问保存的cookie, 那么需要添加一个path属性才可以
document.cookie = "name=zs;path=/;";//把cookie保存在根路径,所有都能访问
-
域名问题:
- 我们在www.it666.com下面保存了一个cookie,
- 那么我们在edu.it666.com中是无法访问的
- 如果想在edu.it666.com中也能访问, 那么我们需要再添加一个domain属性才可以;
所以想要保存一个都可以访问的cookie需要像以下方式保存,可以跨域名,并且在同一个站点访问
document.cookie = "name=zs;path=/;domain=127.0.0.1;";
封装Cookie:
// 创建一个Cooike
// day过期的时间,path保存的路径,domain域名
function addCookie(key, value, day, path, domain) {
// 1、处理没有传递路径的问题
// 获取到当前网页的路径
var lujing = window.location.pathname;
//这是获取到当前,默认的cookie路径都是当前目录的上一级
// 通过lastIndexOf找到最后一个/的索引值
var index = lujing.lastIndexOf('/');
// 使用slice函数保留0到index的部分
var currentPath = lujing.slice(0, index);
//要是传入了path就等于传入的没有传入就等于默认的
path = path || currentPath;
// 2、处理没有传递domain
// 要是传入了domain就等于传入的没有传入就等于当前网站自己的域名
domain = domain || document.domain;
// 3、处理默认的过期时间
// 不传时间则代表默认时间
if (!day) {
document.cookie = key + "=" + value + ";path =" + path + ";domain =" + domain + ";";
} else {
var date = new Date();
date.setDate(date.getDate() + day);
document.cookie = key + "=" + value + ";expries =" + date.toGMTString() + ";path =" + path + ";domain =" + domain + ";";
}
}
// 获取一个Cookie
function getCookie(key) {
// 将Cookie获取并且由;切割
var res = document.cookie.split(";");
// 遍历数组
for (let i = 0; i < res.length; i++) {
const element = res[i];
// 将每一个cookie都用过=分割,这样这个数组的第一个就是key,第二个就是value
var temp = element.split("=");
// 将key左右的空格去掉进行判断
if (temp[0].trim() === key) {
// 如果绝对等于那就将value返回
return temp[1];
}
}
}
// 删除一个Cookie
function delCookie(key, path) {
// 默认情况下只能删除默认路径中保存的cookie,如果想要删除指定路径保存的cookie,则需要在删除的时候指定路径
// 只要在相同key的情况下将保存时间改成昨天的保存时间,那么就直接删除了添加的cookie
addCookie(key, getCookie(key), -1,path);
}
Cookie有一个缺点就是无法分享给别人使用,要是分享给别人就无法的到浏览到多少页的信息了,但是Hash就不会有这种问题
Hash:
hash就是在网址后面做一个标记,这个标记得到的是页数,然后要是分享给别人,别人也可以直接跳转到你浏览的页面
hash值就是在网站后面的#+数字,得到一种标记
// 种一个hash
// 使用document.location.hash = 数字;
document.location.hash = 2;
// 在控制台打印一个hash值
// 因为hash值是一个#+数字,所以可以忽略#直接得到数字,通过subString()
console.log(document.location.hash.substring(1));
通过jQuery发送ajax
$.ajax()
形式:$.ajax({name:val, name:val,…});
可选字段:
- url:链接地址,字符串表示
- data:需发送到服务器的数据,GET与POST都可以,格式为{A: ‘…’, B: ‘…’}
- type:“POST” 或 “GET”,请求类型
- timeout:请求超时时间,单位为毫秒,数值表示
- cache:是否缓存请求结果,bool表示
- contentType:内容类型,默认为"application/x-www-form-urlencoded"
- dataType:服务器响应的数据类型,字符串表示;当填写为json时,回调函数中无需再对数据反序列化为json
- success:请求成功后,服务器回调的函数
- error:请求失败后,服务器回调的函数
- complete:请求完成后调用的函数,无论请求是成功还是失败,都会调用该函数;如果设置了success与error函数,则该函数在它们之后被调用
- async:是否异步处理,bool表示,默认为true;设置该值为false后,JS不会向下执行,而是原地等待服务器返回数据,并完成相应的回调函数后,再向下执行
- username:访问认证请求中携带的用户名,字符串表示
- password:返回认证请求中携带的密码,字符串表示
不知道将最后两个放到data中去,是不是密码会以明文展示,因没有尝试过,这里不敢下结论。
$.ajax({
url: "/greet",
data: {name: 'jenny'},
type: "POST",
dataType: "json",
success: function(data) {
// data = jQuery.parseJSON(data); //dataType指明了返回数据为json类型,故不需要再反序列化
...
}
});
$.post()
该方法使用POST方式执行Ajax请求,从服务器加载数据。
形式:$.post(url, data, func, dataType);
可选参数:
- url:链接地址,字符串表示
- data:需要发送到服务器的数据,格式为{A: ‘…’, B: ‘…’}
- func:请求成功后,服务器回调的函数;function(data, status, xhr),其中data为服务器回传的数据,status为响应状态,xhr为XMLHttpRequest对象,个人感觉关注data参数即可
- dataType:服务器返回数据的格式
$.post(
"/greet",
{name: 'Brad'},
function(data) {
...
},
"json"
);
$.get()
该方法使用GET方式执行Ajax请求,从服务器加载数据。
形式:$.get(url, data, func, dataType);
可选参数:
- url:链接地址,字符串表示
- data:需要发送到服务器的数据,格式为{A: ‘…’, B: ‘…’}
- func:请求成功后,服务器回调的函数;function(data, status, xhr),其中data为服务器回传的数据,status为响应状态,xhr为XMLHttpRequest对象,个人感觉关注data参数即可
- dataType:服务器返回数据的格式
$.get(
"/greet",
{name: 'Brad'},
function(data) {
...
},
"json"
);
$.getJSON()
该方法使用GET方式执行Ajax请求,从服务器加载JSON格式数据。
形式:$.getJSON(url, data, func);
因为确定服务器返回json编码的数据,故相较于$.get()不必再指定dataType。
$.getJSON(
"/greet",
{name: 'jenny'},
function(data) {
...
}
);
$.load()
该方法将服务器加载的数据直接插入到指定DOM中。
形式:$.load(url, data, func);
其中data如果存在则使用POST方式发送请求,不存在则使用GET方式发送请求。
<div id="ret"></div>
$('#ret').load(
"/greet",
{name: 'Brad'}
);
$.getScript()
该方法使用GET方式执行Ajax请求,从服务器加载并执行回传的JavaScript。
形式:$.load(url, func);
开发过程中的问题
如果服务器传过来的是一个非标准的JSON
如果服务器传过来的是一个非标准的JSON字符串,则会导致不能使用原生JS的自带JSON.parse()方法来转换成对象,这时候有两种方法可以解决此问题
- 第一种:和后端开发人员反应
- 第二种:使用eval()
要是没有获取到正确的JSON字符串,则可以使用eval来强制转换成对象,无论是标准的JSON还是非标准的JSON,都可以通过eval来转换成对象,但是需要在这个字符串的左右使用圆括号进行拼接
// var str = '{error: 0, id: 1, time: 1526541587, acc: 0, ref: 0}';
var str = '{"error": "0", "id": "1", "time": "1526541587", "acc": "0", "ref": "0"}';
// var obj = JSON.parse(str);
// console.log(obj);
var obj = eval("("+str+")");
console.log(obj);