AJAX
关于ajax和异步
什么是ajax?
交互式网站开发技术
实现动态更新(局部)的内容
优点:
提升浏览器的加载速度
实现了局部刷新
表单验证(增强用户体验)
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术
本质:是在HTTP协议的基础上以异步的方式通过XMLHttpRequest对象与服务器进行通信。
作用:可以在页面不刷新的情况下,请求服务器,局部更新页面的数据;
1.ajax编程
1.1异步(Asynchronous)
指某段程序执行时不会阻塞其它程序执行,其表现形式为程序的执行顺序不依赖程序本身的书写顺序,相反则为同步。
其优势在于不阻塞程序的执行,从而提升整体执行效率。
同步:同一时刻只能做一件事,上一步完成才能开始下一步
异步:同时做多件事,效率更高
XMLHttpRequest可以以异步方式的处理程序。
1.2XMLHttpRequest
前端的register.html文件
<form>
<span id="msg">aaa</span>
用户名:<input type="text" name="username" id="username">
昵称:<input type="text" name="nickname" >
密码: <input type="password" name="password" >
<input type="submit" value="注册">
</form>
前端基于http发送的一个异步请求 前端的get请求(重要)
<script>
document.querySelector("#username").onblur = function(){
// 1.获取用户数据
var name = this.value;
// 2,让异步对象发送请求
// 2.1 创建异步对象
var xhr = new XMLHttpRequest();
// 2.2 设置 请求行 open(请求方式,请求url):
// get请求如果有参数就需要在url后面拼接参数,
xhr.open("get","validate.php?username="+name);
// 2.3 设置 请求头 setRequestHeader('key':'value')
// get方式不需要设置请求头
// 2.4 设置 请求体:发送请求 send(参数:key=value&key=value)
// 对于 get请求不需要在这个位置来传递参数
xhr.send(null);
// 响应报文:
// 报文行:响应状态码 响应状态信息 200 ok
// 报文头:服务器返回给客户端的一些额外信息
// 报文体:服务器返回给客户端的数据 responseText:普通字符串 responseXML:符合xml格式的字符串
// xhr.status:可以获取当前服务器的响应状态 200 》成功
console.log(xhr.status);
// 一个真正成功的响应应该两个方面:1.服务器成功响应 2.数据已经回到客户端并且可以使用了
// 监听异步对象的响应状态 readystate
// 0:创建了异步对象,但是还没有真正的去发送请求
// 1.调用了send方法,正在发送请求
// 2.send方法执行完毕了,已经收到服务器的响应内容--原始内容,还不可以使用
// 3.正在解析数据
// 4.响应内容解析完毕,可以使用了
xhr.onreadystatechange = function(){
//等待浏览器返回成功并且解析完毕
if(xhr.status == 200 && xhr.readyState == 4){
console.log(xhr.responseText);
console.log("-----------");
document.querySelector(".showmsg").innerHTML = xhr.responseText;;
}
}
};
</script>
前端的post请求(重要)
<script>
document.querySelector("#username").onblur = function(){
// 1.获取用户数据
var name = this.value;
// 2. 让异步对象发送post请求
// 2.1 创建异步对象
var xhr = new XMLHttpRequest();
// 2.2 设置请求行 open(请求方式,请求url)
// 2.post请求不需要拼接参数
xhr.open("post","validate.php");
// 2.3 设置请求头:setRequestHeader()
// 2.post需要设置请求头:Content-Type:application/x-www-form-urlencoded
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//.如果没有设置,参数无法正确的传递到服务器(本质上说,如果没有参数,也不一定需要设置,不会影响请求的发送)
// 2.4 设置请求体 send()
// 2.post的参数在这个函数中设置(如果有参数)
xhr.send("username="+name);
// 3.让异步对象接收服务器的响应数据
// 一个成功的响应有两个条件:1.服务器成功响应了 2.异步对象的响应状态为4(数据解析完毕可以使用了)
// 当异步对象的响应状态发生改变的时候,会触发一个事件:onreadystatechange
xhr.onreadystatechange = function(){
// 判断服务器是否响应 判断异步对象的响应状态
if(xhr.status == 200 && xhr.readyState == 4){
document.querySelector(".showmsg").innerHTML = xhr.responseText;
}
}
};
</script>
处理后端的php文件`
<?php
header('content-type:text/html;charset=utf-8');
if($_SERVER['REQUEST_METHOD'] == 'POST'){
//获取用户名
$name=$_POST['username'];
//判断数据库中是否已有这个用户名
$names=['jack','rose','tom','lili'];
//有则注册失败,否则成功
if(in_array($name,$names)){
$str = '这个名字太火了,换一个吧!';
echo $str;
}else{
$str = '恭喜,名字可用!';
echo $str;
}
}
?>
API 详解
xhr.open() 发起请求,可以是get、post方式
xhr.setRequestHeader() 设置请求头
xhr.send() 发送请求主体get方式使用xhr.send(null)
xhr.onreadystatechange = function () {} 监听响应状态
readstate 属性有五个状态:
xhr.readyState = 0时,(未初始化)还没有调用send()方法
xhr.readyState = 1时,(载入)已调用send()方法,正在发送请求
xhr.readyState = 2时,(载入完成)send()方法执行完成,已经接收到全部响应内容
xhr.readyState = 3时,(交互)正在解析响应内容
xhr.readyState = 4时,(完成)响应内容解析完成,可以在客户端调用了
不用记忆状态,只需要了解有状态变化这个概念
xhr.status表示响应码,如200
xhr.statusText表示响应信息,如OK
xhr.getAllResponseHeaders() 获取全部响应头信息
xhr.getResponseHeader(‘key’) 获取指定头信息
xhr.responseText、xhr.responseXML都表示响应主体
注GET和POST请求方式的差异(面试题)
1、GET没有请求主体,使用xhr.send(null)
2、GET可以通过在请求URL上添加请求参数
3、POST可以通过xhr.send(‘name=itcast&age=10’)
4、POST需要设置
5、GET大小限制约4K,POST则没有限制
1.3 使用异步对象发送读取JSON文件
JSON格式的数据和特点
描述数据的一种格式
[
{
"src":"./images/nav_1.png" ,
"text":"京东超市"
},
{
"src":"./images/nav_2.png" ,
"text":"全球购物"
},
{
"src":"./images/nav_3.png" ,
"text":"京东市场"
}
]
规则和特点
关于json的描述
1,一组花括号表示一个对象,一个对象通过键值对写入一堆相关数据
2,一组方括号表示一个数组,多组对象通过数组的方式装载
3,对象的所有属性都必须加上双引号,值没有undefined
4,文件后缀名为.json,json格式的数据内不允许写注释
操作json的方法
前端(Javascript)操作json的方式
JSON.parse(json字符串) 将json格式的字符串转换为数组或者对象
JSON.stringify(对象或者数组) 将字面量对象或者数组转换为json格式的字符串
php操作json的方式
json_decode(json字符串) 将json格式的字符串转换为php的数组或者对象
json_encode(关联数组) 将php的数组转换为json字符串
关于json的操作
<script>
// 让异步对象发送异步请求
// 1.创建对象
var xhr = new XMLHttpRequest();
// 2.设置请求行
xhr.open("get", "./server/nav-json.php");
// 3.设置请求头:get不需要设置
// 3.设置请求体
xhr.send();
// 让异步对象接收服务器响应数据:一个成功的响应包含两个条件:1.服务器成功响应了 2.数据解析完毕可以使用了
xhr.onreadystatechange = function() {
if (xhr.status == 200 && xhr.readyState == 4) {
var result = xhr.responseText;
var data = JSON.parse(result);
var html = "";
for (var i = 0; i < data.length; i++) {
html += "<li>";
html += '<a href="#">';
html += '<img src="' + data[i].src + '" alt="">';
html += '<p>' + data[i].text + '</p>';
html += '</a>';
html += '</li>';
}
// 将生成的页面结构添加到dom元素中
document.querySelector("ul").innerHTML = html;
}
}
</script>
后端处理php文件的代码
<?php
echo file_get_contents("../data/nav.json");
?>
1.4封装AJAX工具函数
// type:请求方式
// url:请求url
// data:传递给服务器的参数
// callback:客户端的动态结构的渲染方式
// 下面的封装方式的缺点:
// 1.参数数量固定:用户在调用的时候必须传入四个参数
// 2.参数的顺序固定:用户在调用的时候必须按照顺序进行参数的传递
// 3.不方便后期封装功能的扩展与修改
// function ajax(type,url,data,callback){}
// 解决方式:通过传入对象的方式来设置参数
// option是一个对象,它里面包含着相关的属性:如type,url,data,callback
// 不方便后期功能的添加与扩展
// 会造成当前文件中存在着大量的全局变量,会造成全局变量污染
// function ajax(option){}
// function get(option){}
// function post(option){}
// 建议的封装方式:
var $ = {
// 将{"name":"jack","age":20} 的参数要转换为 ?name=jack&age=20
getpa:function(data){
if(data && typeof data == "object"){
var str = "?";
for(var key in data){
str = str + key + "=" + data[key] + "&";
}
str = str.substr(0,str.length-1);
}
return str;
},
// option.type:请求方式
// option.url:请求的url
// option.data:当前请求所传递的参数:规定参数必须是以对象的形式传递{"name":"jack","age":20}
// option.success:渲染方式
ajax:function(option){
// 接收用户参数进行相应处理
var type = option.type || 'get';
// location.href 可以获取当前文件的路径
var url = option.url || location.href;
// 接收参数:在js中最方便收集的数据类型为对象,所以我们就规定传递的参数必须是对象
var data = this.getpa(option.data) || "";
// 响应成功之后的回调
var success = option.success;
// 创建异步对象
var xhr = new XMLHttpRequest();
// 让异步对象发送请求
// 请求行
if(type == "get"){
// 拼接参数
url += data;
data = null;
}
xhr.open(type,url);
// 请求头
if(type == "post"){
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
// 请求体
xhr.send(data);
// 让异步对象接收响应
xhr.onreadystatechange = function(){
// 一个成功的响应有两个条件:1.服务器成功响应 2.数据解析完毕可以使用
if(xhr.status == 200 && xhr.readyState == 4){
// 接收响应的返回值
// responseText responseXML
var rh = xhr.getResponseHeader("Content-Type");
// 判断
if(rh.indexOf("xml") != -1){
var result = xhr.responseXML;
}
else if(rh.lastIndexOf("json") != -1){
var result = JSON.parse(xhr.responseText);
}else{
var result = xhr.responseText;
}
// 接收数据之后,调用回调函数
success && success(result)
}
}
},
get:function(option){
},
post:function(){
}
}
2.jQuery中的ajax
$.ajax({这里传入一个字面量对象}) 参数说明
url 接口地址
type 请求方式
timeout 请求超时,单位是毫秒
dataType 服务器返回的格式, json / xml / jsonp
data 发送请求的数据
beforeSend: fucntion() { …code } 请求发起前的调用
success: fucntion() { …code } 成功响应后的调用
error: fucntion() { …code } 错误响应时的调用,e参数为报错信息
complete: fucntion() { …code } 响应完成时的调用
async true/false(默认true,异步;false,同步)
完整的jQuery调用(重要)
$.ajax({
type: 'post',
url: './server/nav-json.php',
data: {}, //请求需要传递的参数
// 设置请求超时:单位为毫秒,如果服务器的响应时间超过指定的时候,请求失败
timeout: 3000,
dataType:'json', // 设置响应数据的格式 xml json text html script jsonp
// 发送请求之前的回调
beforeSend:function(){
// 在这个回调函数中,如果return false,那么本次请求会中止
// return false;
},
success: function() {
//请求成功之后的回调
},
// 请求失败之后的回调
error:function(e){
if(e.statusText == "timeout"){
alert("请求超时,请重试");
}
},
// 无论请求是成功还是失败都会执行的回调
complete:function(){
console.log('实现一些全局成员的释放,或者页面状态的重置....');
}
});
1.jQuery中ajax的其他用法
1.1$.get()的使用
本质上只能发送get请求
$.get(url, data, success, datatype) 说明
url 所请求的url
data 请求所传递的数据
success: function() { …code } 成功之后的回调
datatype: 需要返回的数据类型
.
g
e
t
(
"
.
/
s
e
r
v
e
r
/
n
a
v
−
j
s
o
n
.
p
h
p
"
,
f
u
n
c
t
i
o
n
(
)
/
/
成
功
回
调
之
后
的
函
数
,
"
j
s
o
n
"
)
1231.2
.get("./server/nav-json.php", function() { // 成功回调之后的函数 }, "json") 1 2 3 1.2
.get("./server/nav−json.php",function()//成功回调之后的函数,"json")1231.2.post()的使用
参数一致,用法一直,目的一致
代码略.
3.模板引擎
Js插件: template_native.js
作用:渲染数据时 代替 拼接字符串的操作
如果数据是一个对象,就直接传入对象
如果数据是一个数组,就包装对对象再传递
因为在模板中只能使用当前传入的对象的属性,它会根据属性自动的去获取对应的值来使用
3.1原生语法(遍历用for)
1.单个数据的结构生成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
**2.多个数据的动态结构生成 **
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
3.2标准语法(遍历用each as)
<script src="./js/jquery.min.js"></script>
<script src="./js/template.js"></script>
<script>
// 发送ajax请求
$.ajax({
url: "./music.php",
dataType: 'json',
success: function (result) {
// 调用模板引擎动态生成页面结构
// 如果参数是对象是直接传入对象
// 如果参数是数组,就包装为对象
var html = template("musicTemp",{"items":result});
$("tbody").html(html);
}
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
4.同源&跨域
同源策略是浏览器的一种安全策略,所谓同源是指,域名,协议,端口完全相同。
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。那什么是跨域呢,简单地理解就是因为JavaScript同源策略的限制,a.com域名下的js无法操作b.com或是c.a.com域名下的对象。
当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。
注意:跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。之所以会跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致
例如http://www.example.com/
http://api.example.com/detail.html 不同源 域名不同
https//www.example.com/detail.html 不同源 协议不同
http://www.example.com:8080/detail.html 不同源 端口不同
http://api.example.com:8080/detail.html 不同源 域名、端口不同
https://api.example.com/detail.html 不同源 协议、域名不同
https://www.example.com:8080/detail.html 不同源 端口、协议不同
http://www.example.com/detail/index.html 同源 只是目录不同
说明
第一:如果是协议和端口造成的跨域问题“前端”是无能为力的
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会根据域名对应的IP地址是否相同来判断。“URL的首部”可以理解为“协议, 域名和端口必须匹配”
所有跨域都必须经信息提供方允许, 如果未经允许即可获取, 那是浏览器同源策略出现漏洞
实现跨域
1.服务器端设置CORS跨域(cross-origin resource sharing 跨域资源共享)
1
2
3
4
5
6
7
2.jsonp的实现原理
页面中有几个标签允许跨域请求资源 a链接的href 、 img的src 、link的href 、script的src
1.主要是利用了script标签的天然的跨域特性来发送请求
2.它的实现方式:在发送请求的时候传递一个函数名称给后台,后台返回数据的时候会返回这个函数的调用形式,并且在()中拼接参数
3.ajax和jsonp的本质不一样。ajax的核心是通过XMLHttpRequest来发送请求,而jsonp是通过script标签来实现请求的发送
实现方式
先定义一个函数,然后动态创建script src去请求资源
在请求地址后面要加参数(参数名=函数名)
后台拿到函数名,再以函数名调用的形式返回
拿到数据直接调用
前端开启跨域请求(dataType:“jsonp”)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
后端进行拼接(拼接字符串)
1
2
3
4
5
6
7
8
获取天气案列
date | dayPictureUrl | nightPictureUrl | temperature | weather | wind |
---|
a) 设置超时 xhr.timeout
b) 监听超时事件 xhr.ontimeout = function () {// code}
发送请求 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 5.2 FormData(获取表单元素) form内表单元素的name属性是必须的,但是不需要再一个个获取了formdata.append(“address”,“传智播客”);可以自由的追加参数
a) 提供了一个新的内建对象,可用于管理表单数据
b) 首先要获取一个表单元素form
c) 然后在实例化时 new FormData(form),将表单元素form传进去
d) 会返回一个对象,此对象可以直接做为xhr.send(formData)的参数
e) 此时我们的数据就是以二进制形式传递了(不需要设置请求头)
f) 注意我们这里只能以post形式传递,浏览器会自动为我们设置一个合适的请求头
用户名: 密码: 电话: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 传统获取表单元素方法前端
用户名: 密码: 电话: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 5.3 上传文件的POST请求 **注意:**这里设置了请求头的话,数据无法传递前端
用户名: 密码: 头像:1
2
3
4
5
5.4 onprogress监听文件上传的进度
注意:这段代码一定要在send方法之前
// 监听文件上传的进度:这个监听必须在send之前来设置
xhr.upload.onprogress = function(e) {
var current = e.loaded; //上传了多少
var total = e.total; //总共
var percent = current / total * 100 + “%”;
document.querySelector(".in").style.width = percent;
document.querySelector(“span”).innerHTML = Math.floor(current / total * 100) + “%”;
}
xhr.send(formData);
————————————————
版权声明:本文为CSDN博主「商晓沐」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45520598/article/details/100062176