Ajax学习第一天
•传统网站中存在的问题
- 网速慢导致的页面加载时间过长
- 表单重填问题
- 页面的跳转问题(有时候页面中只需要某个特定部分实现改变而使整个页面发生跳转)
以上的问题导致用户体验不佳,故提出Ajax解决方案,它是浏览器提供的一套方法,实现页面无刷新更新数据,它是运行在客户端上的。
•应用场景
页面上拉加载更多数据
列表分页
表单验证
搜索框提示文字下拉列表
•运行环境
Ajax技术需要运行在网络环境中才能生效(以域名的方式进行访问)
•运行原理
在传统的浏览器端与服务器端直接进行交互之间增加Ajax 使开发人员对整个过程可控。
•实现步骤
创建Ajax对象
var xhr = new XMLHttpRequest();
告诉Ajax请求地址及请求方式
xhr.open('get','http://www.example.com');
发送请求
xhr.send();
获取服务器端给与客户端的响应数据
xhr.onload=function(){ console.log(xhr.responseText);}
•注意事项
在http请求与响应过程中,无论是请求参数还是响应内容,如果是对象类型,最终都会转换为对象字符串进行传输。
1 | JSON.parse(); //将json字符串转换为json对象 |
Ajax学习第二天
•请求参数传递
Get请求方式
请求参数需要自己拼接并且需要注意拼接的格式和方法xhr.open('get','http://www.examples.com?name='zhangsan'&age=20');
Post请求方式
需要设置请求报文头xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
并且在send()函数中填写拼接的参数xhr.send('name='zhangsan'&age=20');
•请求报文
在HTTP请求和响应的过程中传递的数据块就叫做报文,包括要传送的数据和一些附加信息,这些数据和信息要遵守规定好的格式。
•请求参数的格式
application/x-www-form-urlencoded
name='张三' & age = 20 & sex = '男';
application/json
{name:'张三' , age: 20 , sex : '男'};
在请求头中指定Content-Type属性的值是application/json 告诉服务器端当前请求参数的格式是jsonJSON.stringify() //将json对象转换为json字符串
注意:get请求是不能提交json对象数据格式的,传统网站的表单提交也是不支持json对象数据格式的。
•获取服务器端的响应
Ajax状态码
在创建Ajax对象,配置Ajax对象,发送请求,以及接受完服务器端响应数据,这个过程中的每一个步骤都会对应一个数值,即为Ajax状态码
- 0:请求未初始化(还未调用open)
- 1:请求已经建立但是还未发送(还未调用send)
- 2:请求已经发送
- 3:请求正在处理中,通常响应中已有部分数据
- 4:响应已经完成,可以获取并使用服务器响应了
1 | xhr.readyState //获取Ajax状态码 |
onreadystatechange事件
当Ajax状态码发生变化时将自动触发该事件
代码如下:
1 | //注意:此方法目前已经不再流行 |
onload事件与onreadystatechange事件的区别
区别 | onload事件 | onreadystatechange事件 |
---|---|---|
是否兼容IE低版本 | 不兼容 | 兼容 |
是否需要判断Ajax状态码 | 不需要 | 需要 |
被调用次数 | 一次 | 多次 |
•Ajax错误处理
- 网络畅通,服务器端能接收到请求,服务器端返回的结果不是预取结果
解决办法:可以判断服务器端返回的状态码,分别进行处理,xhr.status
可以用以获取http状态码; - 网络畅通,服务器端没有接收到请求,返回404状态码
解决办法:检查请求地址是否错误; - 网络畅通,服务器端能接收到请求,服务器端能接收到请求,服务器端返回500状态码
解决办法:服务器端错误,找后端开发人员进行沟通 - 网络中断,请求无法发送到服务器端
解决办法:会触发xhr对象下面的onerror事件,在onerror事件处理函数中对错误进行处理
Ajax状态码与HTTP状态码的区别
区别 | 含义 | 返回值 |
---|---|---|
Ajax状态码 | Ajax请求的进程状态 | Ajax对象返回的 |
HTTP状态码 | 请求的处理结果 | 服务器端返回的 |
Ajax学习第三天
今天主要围绕以下两个问题解决:
1. 低版本IE浏览器的缓存问题
解决方案:在请求地址的后面加上请求参数,保证每一次请求中的请求参数的值不相同即可。xhr.open('get','http://www.example.com?t='+Math.random());
2. 发送一次请求代码过多,发送多次请求代码冗余且重复
解决方案:将请求代码封装到函数中,发请求时调用函数即可。封装Ajax代码如下:
1 | <body> |
大致思路总结如下:
封装请求类型:判断请求类型为 get / post;
封装请求报文头类型:application/x-www-form-urlencoded application/json
若为后者,则需要在将拼接的字符串类型转换为JSON字符串类型,使用函数JSON.stringify();
封装服务器端返回结果:
- 判断http状态码,使用
xhr.status
若状态码为200 则调用成功函数 若为其它,则调用错误函数。 - 一般情况下,服务器端返回JSON数据作为响应内容,但是客户端拿到的是JSON字符串,所以我们最好将JSON字符串转换为JSON对象,这样函数调用者方便修改数据。
使用函数xhr.getResponseHeader('Content-Type');
得到服务器返回的类型,若得到的是application/json类型,则将服务器返回的数据转换为JSON对象responseText = JSON.parse(responseText);
若得到text/html类型,则不做处理
- 判断http状态码,使用
封装用户是否传值:若用户设置相关内容,则使用用户设置的相关内容,否则使用默认值,要注意对象覆盖函数的用法!
Object.assign(defaults, options);
Ajax学习第四天
今天主要是写了两个案例,这两个案例还是单独开一栏写好了,这里介绍一下模板引擎的使用。
作用:使用模板引擎提供的模板语法,可以将数据和HTML拼接起来,这里我使用 的是art-template,使用步骤如下:
下载 art-template 模板引擎库文件并在HTML页面中引入库文件
准备 art-template 模板
1
2
3
4<script type="text/html" id="tpl">
<div id="box">
</div>
</script>告诉模板引擎将哪一个模板和哪个数据进行拼接
var html = template('tpl',{username:'zs',age:'20'});
将拼接好的html字符串添加到页面中
document.getElementById('contaoner').innerHTML = html
通过模板语法告诉模板引擎,数据和html字符串要如何拼接
1
2
3
4
5<script type="text/html" id="tpl">
<div id="box">
<h1>{{username}},{{age}}</h1>
</div>
</script>
Ajax学习第五天
FormData及同源政策
背景:由前几天的学习可以知道,当对表单数据进行提交的时候,Ajax需要我们指明需要提交的属性及数据并进行拼接,在这之前,我们必须手动获取对应控件的相关内容,一旦数据量过大,就很容易造成拼接错误等问题,所以提出了FormData这一解决方案。
FormData对象的作用
1. 模拟HTML表单,相当于将HTML表单映射成表单对象,自动将表单对象中的数据拼接成请求参数的格式; 2. 异步上传二进制文件(例如:图片 视频及音频文件)。
FormData对象的使用
准备HTML表单,不用设置请求地址及请求方式,也不用将input控件中的按钮设置为submit,设置为button即可,因为若设置为submit方式,表单会自动进行提交,从而使FormData不生效,值得注意的是,必须为需要提交数据的控件设置name属性;
1
2
3
4<form id="form">
<input type="text" name="username">
<input type="password" name="password">
<input type="button" id="btn" value="提交">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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
2. 利用FormData构造函数,将HTML表单转化为FormData对象
``var form = document.getElementById('form');``
``var formData = new FromData(form);``
3. 提交表单对象,采用此方法提交表单时,**不支持get方法**
``xhr.send(formData);``
- **FormData对象的实例方法**
1. 获取表单对象中属性的值
``formData.get('key');``
2. 设置表单对象中属性的值,**如果表单控件不存在,则会自动创建这个表单属性**
``formData.set('key','value');``
3. 删除表单对象中属性的值
``formData.delete('key');``
4. 向表单对象中追加属性值,**它可以在空的表单对象中追加值**
``formData.append('key','value');``
**与 set 方法的区别**:在属性名已存在的情况下,set 方法会覆盖已有键名的值,append 会保留两个值,但是服务器端需要响应的设置,否则,仍然传递最后一次的值。
- **FormData对二进制文件的上传及文件上传进度的展示**
代码如下:
```javascript
<!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>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="form-group">
<label>请选择文件</label>
<input type="file" id="file">
<br/>
<div class="progress">
<div class="progress-bar" style="width: 0%;" id="progress">0%</div>
</div>
</div>
</div>
<script>
//获取文件控件
var file = document.getElementById('file');
//对文件控件田间发生改变事件
file.onchange = function () {
//创建空的FormData构造函数
var formData = new FormData();
//将file控件中选择的文件追加到formData中
// 第一个参数开发过程中由后端人员提供 第二个参数代表选择的文件
formData.append('attrName',this.files[0]);
//创建Ajax对象
var xhr = new XMLHttpRequest();
//配置Ajax对象
xhr.open('post','http://localhost/foemData');
//在文件上传的过程中持续触发
xhr.upload.onprogress = function(ev){
//ev.loaded 文件已经上传了多少
//ev.total 上传文件总大小
var pro = (ev.loaded / ev.total)*100+'%';
//获取进度条
var progress = document.getElementById('progress');
//设置进度条的宽度
progress.style.width = pro;
//设置进度条的数值
progress.innerHTML = pro;
}
xhr.send(formData);
xhr.onload = function(){
console.log(xhr.responseText);
}
}
</script>
</body>
</html>
FormData文件上传图片即使预览
在我们将图片上传到服务器以后,服务器通常都会将图片地址作为响应数据传递到客户端,客户端可以从响应数据中获取图片地址,然后将图片再显示到页面中,值得注意的是,客户端得到地址后,需要动态的创建img标签,即首先var img = document.createElement('img');
,再采用box.appendChild(img);
的方式添加到页面上,如果直接将图片地址赋值给img的src,客户会看到图片的加载过程,影响用户体验;在服务端,同样的需要设置,应该引入表单解析对象,即formidable。
接下来是有关昨天做行政区联动碰到的问题,大相径庭。
同源政策
Ajax的请求限制:Ajax只能向自己的服务器发送请求,比如说,A网站的服务器端有A的HTML文件,B网站的服务器端有B的HTML页面,此时,A可以向自己的服务器发送Ajax请求,B也可以向自己的服务器发送Ajax请求,但是A不能向B的服务器发送Ajax请求,B也同理。什么是同源
如果两个页面拥有相同的域名,协议及端口,那么我们称这两个页面是同源的,其中只要有一个不同,都是不同源的。同源政策的目的
同源政策是为了保证用户信息的安全,防止恶意的网站窃取数据,最初的同源政策是指A网站在客户端防止的Cookie,B网站是不能访问的。使用JSONP解决同源限制问题
JSONP:json with padding的简称 它不属于Ajax请求,但它可以模拟Ajax请求使用JSONP解决同源限制问题的步骤
- 将不同源的服务器端请求地址写在script标签的src属性中,因为script标签不受同源政策的影响
``<script src="www.example.com"></script>``
- 服务器端响应数据必须是一个函数的调用,真正要发送给客户端的数据需要作为函数调用的参数
``const data = 'fn({name:'zhangSan',age:'20'})';`` ``res.send(data);``
- 在客户端全局作用域下定义函数fn,这个函数需要写在script标签的前面
``function fn(data){ }``
- 在fn函数内部对服务器端返回的数据进行处理
``function fn(data){console.log(data)}``
- 将不同源的服务器端请求地址写在script标签的src属性中,因为script标签不受同源政策的影响
Ajax学习第六天
Ajax学习第六天——JSONP代码优化,使用最初版本的JSONP代码,即昨天博客上写的步骤,会有以下3个问题:
使用JSONP方法时,每次都要将函数名称发送给服务器端,一旦服务器端程序员修改函数名,前端界面也要一起修改,造成了沟通成本的增加;
一旦出现有多个请求时,采用此时的JSONP代码会出现若第一个请求还未执行完成,发送第二个请求,服务器端会覆盖第一次请求的结果,导致第一次的请求结果被覆盖;
若多次调用JSONP,要重复编写大量相似且冗余的代码,比较繁琐。
针对以上3个问题,提出以下3个要求:
无论怎么修改函数名,都不需要前端后端程序员重新沟通;
将script的请求的发送变成动态请求;
封装JSONP函数,方便请求发送。
实现以上三个要求的代码如下(本代码针对前端,服务器端代码未贴出):
1 | <!DOCTYPE html> |
Ajax学习第七天
Ajax学习第七天——CORS跨域资源共享及jQuery中$.ajax()的使用
第二种解决非同源数据的方案
CORS:Corss orgin resource sharing 即跨域资源共享,它允许浏览器向跨域服务器发送Ajax请求,克服了Ajax只能同源使用的限制。
具体使用:需要在服务器端进行配置,客户端无需配置
服务器端代码如下:
1 | app.get('/cross',(req,res) => { |
第三种解决非同源数据的方案
同源政策是浏览器给予Ajax技术的限制,服务器端是不存在同源政策限制的,因此我们可以先将客户端的请求发送给自己的服务器端,由自己的服务器端与非同源的服务器端进行访问,拿到数据后,再将数据返回给自己的客户端,相当于在自己的客户端与非同源服务器端之间增加了一座桥梁,就是自己的服务器端。
本方法的提出要先了解Cookie的作用,最初的时候,客户端与服务器端使用HTTP协议进行连接,它们之间的连接是无状态的,即没有记录功能,相当于两端都互不认识,Cookie提出后,相当于一张它们的名片,使得客户端与服务器端彼此认识,这时他们彼此就可以互相访问了。
withCredentials属性
在使用Ajax技术发送跨域请求时,默认情况下不会再请求种携带Cookie信息,所以它们彼此的访问是不被允许的。此时,只需修改本属性的值为true即可,需要在客户端与服务器端都进行配置。
服务器端代码添加以下一行:// 允许客户端发送跨域请求时携带Cookie信息
res.header('Access-Control-Allow-Credentials',true);
客户端代码添加以下一行:// 当发送跨域请求时携带Cookie信息 默认值为false
xhr.withCredentials = true;
jQuery中 $.ajax() 的使用
jQuery中将Ajax已经封装好了,使用即可,其中有几个属性注意一下使用方式即可
ContentType: 表示发送数据的类型,默认为 application/x-www-form-urlencoded
data: 表示传入的数据,可以传对象,也可以传字符串,最终它都会把它转换为字符串处理
beforeSend:function(){} 表示在请求发送之前会调用此函数,可以放入等待缓冲的图片,提高用户体验
dataType:’jsonp’ jQuery中的$.ajax()方法还可以发送jsonp请求,这点是比较方便的,有两个可选参数:
josnp:'cb'
表示修改callback参数的名称 即向服务器端传递函数名字的参数名称jsonpCallback:'fnName'
表示指定函数名称,此函数就代替了success那个参数的作用
serialize方法
在使用$.ajax()方法中,如果表单中的元素有很多,我们也需要自己拼接参数的格式,本方法与之前的FormData函数类似,不过FromData存在与HTML5中,有兼容性问题,所以在jQuery中,有此方法来替代
作用:将表单中的数据自动拼接成字符串类型的参数,有且只有这项功能
很多时候我们需要使用到字符串里某一些的值,这时我们将它转换为对象类型就很方便,但是jQuery中并没有相关的方法,所以这里我们把它封装好了,代码及使用场景如下:
1 | <!DOCTYPE html> |
全局事件
只要页面中有Ajax请求被发送,对应的全局事件就会被触发
.ajaxStart() //当请求开始发送时触发
.ajaxComplete() //当请求完成时触发
注意 以上两个事件均需要绑定在 document 上
1 | $(document).on('ajaxStart',function(){ |
以上两个全局事件可以结合NProgrss进度条插件(在页面的最上端有一个进度条可可以展示当前请求状态),提升用户体验。
RESTful风格的API
概述:它是一套关于设计请求的规范
GET:获取
POST:添加
PUT:更新
DELETE:删除
例如:
GET: www.example.com/users 获取用户列表数据
POST: www.example.com/users 创建(添加)用户数据
PUT:www.example.com/users/1 修改用户ID为1的用户信息
DELETE:www.example.com/users/1 删除用户ID为1的用户信息
PUT和DELETE在传统表单中不支持,只有Ajax中支持,具体的要结合相关案例
XML基础
XML:extensible markup language 可扩展标记语言,作用是传输和存储数据
XML DOM:即XML文档对象模型,是W3C组织定义地一套操作XML文档对象的API,浏览器会将XML文档解析成文档对象模型
注:此类型的返回数据已经很少用了,了解即可。