ajax概述
背景
- 在了解 AJAX 之前我们可以简单的认为「JavaScript 能力有限」,因为在此之前 Web 平台提供所有的 API 都只停留在「单机」的阶段。
这样就会造成一些无法实现的功能,例如:
- 无法在实现用户登录功能时,当用户输入邮箱地址显示用户对应的头像。
- 无法在实现用户注册功能时,当用户输入邮箱或用户名就提示是否存在
- 无法在实现留言板功能时,实时看到最新的用户留言。
这些功能的开发都卡在一个相同的问题
需求
- 对服务端发出请求并且接受服务端的响应
- 如果可以通过JS直接发送网络请求,那么web的可能就会更多,随之能够实现的功能也会更多,至少不再是只能开发[单机游戏]
Google Suggest
- AJAX(Asynchronous JavaScript and XML),最早出现在 2005 年的 Google Suggest
- 它不是像 HTML、JavaScript 或 CSS 这样的一种“正式的”技术
- 它是在浏览器端进行网络编程(发送请求、接收响应)的技术方案
- 它使我们可以通过 JavaScript 直接获取服务端最新的内容而不必重新加载页面
- 让 Web 更能接近桌面应用的用户体验
AJAX
- AJAX 就是浏览器提供的一套 API,可以通过 JavaScript 调用,从而实现通过代码控制请求与响应。实现通过 JavaScript 进行网络编程。
- XML:最早在客户端与服务端之间传递数据时所采用的数据格式。
应用场景
- 按需获取数据
- 对用户数据校验
- 自动更新页面内容
- 提升用户体验,无刷新的体验
体验ajax
- 使用 jQuery 中封装的 Ajax,快速体验带来.
- 免费接口:jsonplaceholder.typicode.com/
原生AJAX
发送ajax请求步骤
- 1.创建XMLHttpRequest类型的对象
- 2.准备发送,打开与一个网址之间的连接
- 3.执行发送动作
- 4.指定xhr状态变化事件处理函数
XMLHttpRequest类型对象
- AJAX API中核心提供的是一个XMLHttpRequest类型,所有的AJAX操作都需要使用这个类型。
兼容问题
- var xhr = new XMLHttpRequest();
- IE6兼容:xhr = new ActiveXObject("Microsoft.XMLHTTP");
- 代码演示
//1.获取XMLHttpRequest类型的对象
// 兼容问题
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else {
// IE6兼容
xhr = ActiveXObject("Microsoft.XMLHTTP");
}
open方法开启请求
- 本质上XMLHttpRequest就是JavaScript在web平台中发送HTTP请求的手段,因此发送出去的请求仍然是HTTP请求,同样符合HTTP约定的格式。
语法:xhr.open(method,url);
- method: 要使用的HTTP方法。
- 比如[GET](获取数据)、[POST](提交新的数据)、[PUT](数据中进行更改)、[DELETE](删除数据)等。
- url: 要向其发送请求的url地址,字符串格式。
- 代码演示
// 2.打开连接
// get方式:可在地址后面追加信息,多条用&连接
// post方式,必须通过send方法进行传递数据
xhr.open("get","https://jsonplaceholder.typicode.com/users?id=1");
xhr.open("post","https://jsonplaceholder.typicode.com/users");
setRequestHeader()方法设置请求头
- 此方法必须在 open() 方法和 send() 之间调用
语法:xhr.setRequestHeader(header,value)
- header: 一般设置"Content-Type",传输数据类型,即:服务器需要我们传送的数据类型。
- value: 具体的数据类型,常用"application/x-www-form-urlencoded"和"application/json"。
- 代码演示
// 设置响应头
// get方式不用设置,而post必须设置
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
send方法和请求头
语法:xhr.send(body)
- body: 在XHR请求中要发送的数据体,根据请求头中的类型进行传参。
- 如果是GET方法,无需设置数据体,可以传null或者不传参。
- 代码演示
// 3.执行发送动作
// get方式
// xhr.send(null);
// post方式
xhr.send("name=mh&age=18");
readyState属性
- readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态,由于 readystatechange 事件是在 xhr 对象状态变化时触发(不单是在得到响应时),也就意味着这个事件会被触发多次。
- 如图所示
//1.获取XMLHttpRequest类型的对象
// 兼容问题
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else {
// IE6兼容
xhr = ActiveXObject("Microsoft.XMLHTTP");
}
// 初始化
console.log("UNSEND",xhr.readyState);
// 2.打开连接
xhr.open("post","https://jsonplaceholder.typicode.com/users");
// 创建连接
console.log("OPENED",xhr.readyState);
// 设置响应头
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
// 3.执行发送动作
// post方式
xhr.send("name=mh&age=18");
// 4.指定xhr状态变化事件处理函数
xhr.onreadystatechange = function (){
if(this.readyState === 2){
// 接收到响应头
console.log("HEADERS_RECEIVED",xhr.readyState);
}else if(this.readyState === 3){
// 响应体加载中
console.log("LOADING",xhr.readyState);
}else if(this.readyState === 4){
// 加载完成
console.log("DONE",xhr.readyState);
}
}
事件处理函数
- 一般都是在readyState值为4时,执行响应的后续逻辑。
- 代码演示
// 4.指定xhr状态变化事件处理函数
xhr.onreadystatechange = function (){
if(this.readyState === 4){
console.log(this.responseText);
}
}
同步与异步
显示场景理解
- 同步:一个人在同一个时刻只能做一件事情,在执行一些耗时的操作(不需要看管)不去做别的事,只是等待。
- 异步:在执行一些耗时的操作(不需要看管)去做别的事,而不是等待。
ajax中的实现
- xhr.open()方法第三个参数要求传入的是一个boolean值,其作用就是设置此次请求是否采用异步方式执行。
- 默认:true 异步,如果需要同步执行可以通过传递false实现。
- 同步执行,代码会卡在xhr.send()这一步,等到所有的数据都传输完成,才会往下执行。
建议
- 问题:同步执行的时候,为什么onreadystatechange事件不会被触发
- 因为:onreadystatechange事件,只有在readystate变化的时候才会被触发。当同步执行的时候,全部的数据传输完成后,那么readystate将不会再变化,那么此时注册了事件,也不会再被触发。
- 解决方法:为了让事件更加可靠(一定触发),再发送请求send()之前,一定是先注册onreadystatechange事件。
- 代码演示(不论是同步还是异步都能触发成功)
//1.获取XMLHttpRequest类型的对象
// 兼容问题
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else {
// IE6兼容
xhr = ActiveXObject("Microsoft.XMLHTTP");
}
// 2.打开连接
// 异步执行
// xhr.open("post","https://jsonplaceholder.typicode.com/users",true);
// 同步执行
xhr.open("post","https://jsonplaceholder.typicode.com/users",false);
// 设置响应头
// get方式不用设置,而post必须设置
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
// 4.指定xhr状态变化事件处理函数
xhr.onreadystatechange = function (){
if(this.readyState === 4){
// 加载完成
console.log("DONE",xhr.readyState);
}
}
// 3.执行发送动作
// post方式
xhr.send("name=mh&age=18");
// ajax后面的代码
console.log("after ajax");
响应数据格式
提问
- 如果希望服务端返回一个复杂数据,该如何处理?
- 关心的问题:服务端发出何种格式的数据,这种格式如何在客户端用JavaScript解析。
XML
- 一种数据描述手段
- 淘汰的原因:
- 数据冗余太多。元数据(用来描述数据的数据)占用的数据量比较大,不利于大量数据的网络传输。
- 在其他语言中,比如js解析内部数据时,方法比较复杂,不方便使用。
- 代码演示
<?xml verson="1.0" encoding="utf-8" ?>
<booklist>
<book>
<name>三国演义</name>
<author>罗贯中</author>
<cate>古典名著</cate>
</book>
<book>
<name>西游记</name>
<author>吴承恩</author>
<cate>古典名著</cate>
</book>
<book>
<name>红楼梦</name>
<author>曹雪芹</author>
<cate>古典名著</cate>
</book>
</booklist>
JSON
- JavaScript Object Notation 对象表示法
- 也是一种数据描述手段,类似于JavaScript字面量方式
- 服务端采用JSON格式返回值,客户端按照JSON格式解析数据
JSON格式的数据与对象字面量的区别:
- 1.JSON 数据并不需要存储在变量里面
- 2.结束时不需要写分号
- 3.JSON 数据中的属性名必须加 引号
- 演示代码
// 对象字面量
var obj = {
name:"mw",
age:45,
brother:{
name:"lh",
age:36
}
};
// json格式的数据
{
"name":"zs",
"age":18,
"hobby":["paino","paint"]
}
ES5新增JSON对象
- JSON对象的parse方法
- 参数:字符串(符合JSON格式)
- 返回值:转换成一个对象
- JSON对象的stringify方法
- 演示代码
// 对象字面量
var obj = {
name:"mw",
age:45,
brother:{
name:"lh",
age:36
}
};
// 创建一个符合JSON数据格式的字符串
var str = '{"name":"ff","age":99}';
// es5中新增了JSON对象
// JSON对象的parse方法和stringify方法
// 1.stringify方法
// 将对象字面量转换成 字符串形式
console.log(JSON.stringify(obj));
// 将符合JSON数据格式的字符串,转换成对象
var s = JSON.parse(str);
console.log(s);
// 可以通过打点调用属性
console.log(s.name); // ff
console.log(s.age); // 99
注意
- 不管是JSON还是XML,只是在AJAX请求过程中用到,并不代表它们与AJAX之间有必然的联系,它们只是数据协议。
- 不管服务端采用XML还是JSON,本质上都是将数据返回给客户端。
- 服务端应该根据响应内容的格式设置一个合理的Content-Type.
JSON Server
- 平时会写一些数据,通过ajax获取。所以,需要在本地搭建一个临时服务器。
- json-server是一个Node模块,运行Express服务器,可以指定一个json文件作为api的数据源。
- 可以使用json-server快速搭建一个web服务器。
- 网址:github.com/typicode/js…
原生AJAX具体用法
JSON文件书写方法
在命令行中
- 进入某一个具体的文件夹:输入cd,先不回车,然后在后边输入想要进入的文件夹路径,即可进入该文件夹。(将JSON文件托管到json-server服务端时,要注意路径是否正确)
- 否则会出现:文件找不到的情况,那么服务端会自动创建一个同名的json文件。
- 如下图
GET请求
- 通常在第一次get请求中,参数传递都是通过URL地址中的'?'参数传递。
- 一般在GET请求中,无需设置请求头。
- 无需设置响应体,可以传null或者不传
案例:对自己在服务端部署的JSON文件进行get请求
// 创建xhr对象,兼容写法
var xhr = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");
// 打开链接
// xhr.open(method,url);
// get请求
// 传递参数,筛选获取
xhr.open("get","http://localhost:3000/users?age=15");
// 执行发送
xhr.send(null);
// 指定xhr状态变化事件处理函数
xhr.onreadystatechange = function (){
if(this.readyState === 4){
console.log(this.responseText);
}
}
POST请求
- POST请求过程中,都是采用请求体承载需要提交的数据。
- 需要设置请求头中的Content-Type,以便于服务端接收数据。
- 需要提交到服务端的数据可以通过send方法的参数传递。
案例:对自己在服务端部署的JSON文件进行post请求
- 返回:新增加的数据,并且查看json文件中也已经成功添加了数据,id自动增加。
// 创建xhr对象,兼容写法
var xhr = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");
// 打开链接
// xhr.open(method,url);
// post请求
xhr.open("post","http://localhost:3000/users");
// post请求,必须要设置请求头
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
// 执行发送
xhr.send('name=bb&age=23&class=2');
// 指定xhr状态变化事件处理函数
xhr.onreadystatechange = function (){
if(this.readyState === 4){
console.log(this.responseText);
}
}
// 第一种方法
// post请求,必须要设置请求头
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
// 执行发送
xhr.send('name=bb&age=23&class=2');
// 第二种方法
xhr.setRequestHeader("Content-Type","application/json");
// json数据格式
xhr.send('{"name":"bn","age":23,"class":1}');
// 第三种方法
xhr.setRequestHeader("Content-Type","application/json");
// 对象转字符串
xhr.send(JSON.stringify({
name:"nn",
age:12,
class:2
}));
处理响应数据渲染
- 客户端中拿到请求的数据后,需要把这些数据呈现到界面上。
- 数据结构简单:可以直接通过**字符串操作(拼接)**的方式处理。当数据过于复杂时,不推荐使用,字符串拼接维护成本太大。
- 数据结构复杂:推荐使用模板引擎或者ES6提供的模板字符串。
- 代码演示
* {
margin: 0;
padding: 0;
}
table {
width: 300px;
/* 上下30 左右居中 */
margin: 30px auto;
font: 14px/28px "微软雅黑";
color: #333;
/* 取消边框之间的缝隙 */
border-collapse: collapse;
/* border: 1px solid #666; */
}
td,th {
width: 100px;
}
<!-- table表格中,tr表示一行,th表示表头,td表示每个单元格
其中 th和td 必须在tr中 -->
<table border = "1" class ="box">
<tr>
<th>学号</th>
<th>姓名</th>
<th>班级</th>
<th>年龄</th>
</tr>
</table>
<script src="js/jquery.min.js"></script>
<script>
// 获取元素
// var $box = $(".box");
var box = document.getElementsByClassName("box")[0];
// 创建xhr对象,兼容写法
var xhr = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");
// 打开链接
xhr.open("get","http://localhost:3000/users");
// 执行发送
xhr.send(null);
// 指定xhr状态变化事件处理函数
xhr.onreadystatechange = function (){
if(this.readyState === 4){
// 返回数组 数组也是对象
// console.log(this.responseText);
// 将返回的结构 渲染到表格中
var data = JSON.parse(xhr.responseText);
console.log(data);
var str = "";
for(var i = 0; i < data.length; i++){
// 1. 拼接字符串(适用于:简单数据结构)
str += '<tr><td>'+ data[i].id +'</td><td>'+ data[i].name +'</td><td>'+ data[i].class +'</td><td>'+ data[i].age +'</td></tr>';
// 2.数据结构复杂:推荐使用**模板引擎**或者**ES6提供的模板字符串**
// ES6推荐的模板字符串 可以包含空格
str += `<tr>
<td>${data[i].id}</td>
<td>${data[i].name}</td>
<td>${data[i].class}</td>
<td>${data[i].age}</td>
</tr>`;
}
// console.log("hi");
box.innerHTML += str;
}
}
</script>
封装AJAX库
封装一个ajax函数
- 主要是为了了解封装的过程,一般情况在开发中都是使用第三方提供的 AJAX 库,因为它们可能更加严谨。
- 为了在后续的开发过程中可以更方便的使用这套 API,一般的做法都是将其封装到一个函数中以便调用。
- 代码演示(将封装好的函数单独提取到一个文件中)
<script>
// 封装自己的ajax函数
/* 参数1:{string} method 请求方法
参数2:{string} url 请求地址
参数2:{Object} params 请求参数
参数3:{function} done 请求完成后执行的回调函数
*/
function ajax(method,url,params,done){
// 创建xhr对象,兼容写法
var xhr = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject("Microsoft.XMLHTTP");
// 将method转换成大写
method = method.toUpperCase();
// 参数拼接
var pair = [];
for(var k in params){
pair.push(k + "=" + params[k]);
}
var str = pair.join("&");
// 判断请求方法
if(method === "GET"){
// 字符串拼接 或者 模板字符串
url += "?" + str;
}
xhr.open(method,url);
var data = null;
if(method === "POST"){
// 需要请求头
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
data = str;
}
xhr.send(data);
// 指定xhr状态变化事件处理函数
// 执行回调函数
xhr.onreadystatechange = function (){
if(this.readyState === 4){
// 返回的应该是一个对象,这样客户端更好渲染
done(JSON.parse(xhr.responseText));
}
}
}
// 调用自己写的ajax函数
ajax("get","http://localhost:3000/users",{
name:"zs",
age:45
},function (a){
console.log(a);
});
</script>
发表评论
还没有评论,快来抢沙发吧!