Ajax
Ajax就是异步的JS和XML
-
Ajax的一个最大的特点就是无需刷新页面便可向服务器传输或读写数据(又称无刷新更新页面),这一特点主要得益于XMLHTTP组件XMLHttpRequest对象。
-
在不刷新页面的情况下,向服务器发送请求,获取数据进行处理。
-
核心:XMLHttpRequest对象,提供发送HTTP请求和接收响应的功能,除此之外,还可以使用jQuery等JavaScript库中提供的Ajax方法、Fetch API等技术实现Ajax功能。
异步请求和同步请求:
- 异步请求:在发请求之后,其他的同步任务都已经执行完毕。
- 同步请求:在发送请求之后,需要等到响应完全结束之后才会执行剩下同步任务。
- 默认情况 ajax发送的都是异步请求 通过open方法的第三个参数可以设置同步。
- true 表示异步请求 默认的
- false 表示同步请求 一般不用
1. Ajax经典四步
- 创建ajax对象
let xhr = new XMLHttpRequest();
- 监听成功的响应--服务器响应了数据,就会触发load事件
xhr.onload = () => {
// xhr.responseText 得到服务器响应过来的数据
console.log("接收到响应据:",xhr.responseText);
}
-
设置请求(配置网络请求)
有三个参数
参数一: 请求方式 get , post , put , delete , head ......
参数二: 请求的API (URL-http://127.0.0.1:3000/getData)
参数三: 是否异步(true,false)
xhr.open('get','http://127.0.0.1:3000/getData')
-
发出请求
可以给服务器传递数据 send(请求体)
xhr.send()
2. 通过url把数据传给服务器
关键:
get请求只能通过url把数据传给服务器
在配置网络请求open()中,通过 拼接查询字符串?
拼接
关键代码:
let msg = `userName=${userName.value}&pwd=${pwd.value}`
xhr.open('get','/getData?'+msg)
- 前端结构如下
<h1>通过url把数据扔给服务器</h1>
<hr>
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" id="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="pwd" id="pwd"></td>
</tr>
<tr>
<td></td>
<td>
<button id="btn">GET方式提交</button>
</td>
</tr>
</table>
- js代码如下
let btnEle = document.querySelector('#btn')
let userName = document.querySelector('#username')
let pwd = document.querySelector('#pwd')
let xhr = new XMLHttpRequest()
xhr.onload = () => {
console.log(xhr.responseText);
}
btnEle.onclick = () => {
// 拼接查询字符串?
let msg = `userName=${userName.value}&pwd=${pwd.value}`
// get请求只能通过url把数据传给服务器
xhr.open("get",'/getData?'+msg)
xhr.send()
}
3. 通过请求体把数据传给服务器
关键:
post、put请求不仅能通过url给服务器传递数据
还可以通过请求体把数据传给服务器 send(请求体)
请求体中有多种格式
-
text/plain
默认的请求体类型,如果不设置请求头字段Content-Type,请求体只要是字符串就行,传递的数据形式为x=1&y=2,后端不做任何处理,如后端得到的数据为 x=1&y=2
前端结构如下:
<h1>通过post把数据扔给服务器</h1> <hr> <table> <tr> <td>用户名:</td> <td><input type="text" name="username" id="username"></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="pwd" id="pwd"></td> </tr> <tr> <td></td> <td> <button id="btn">POST方式提交</button> </td> </tr> </table>
js代码如下:
let btn = document.querySelector('#btn') let username = document.querySelector('#username') let pwd = document.querySelector('#pwd') let xhr = new XMLHttpRequest() xhr.onload = () => { console.log(xhr.responseText); } btn.onclick = function () { xhr.open('post','/postData') let msg = `username=${username.value}&pwd=${pwd.value}` // send中写请求体 称为请求体传参 xhr.send(msg) }
-
x-www-form-urlencoded
在发送请求之前,设置请求头字段Content-Type, 一定要在open()之后send()之前
传递的数据形式为 x=1&y=2 , 后端接收到的数据类型是一个对象
关键代码:
let msg = `username=${username.value}&pwd=${pwd.value}` xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
前端结构如下:
<h1>通过post把数据扔给服务器</h1> <hr> <table> <tr> <td>用户名:</td> <td><input type="text" name="username" id="username"></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="pwd" id="pwd"></td> </tr> <tr> <td></td> <td> <button id="btn">POST方式提交</button> </td> </tr> </table>
js代码如下:
const btn = document.querySelector('#btn'); const username = document.querySelector('#username'); const pwd = document.querySelector('#pwd'); let xhr = new XMLHttpRequest() xhr.onload = () => { console.log(xhr.responseText); } btn.onclick = function () { xhr.open('post','/postData') let msg = `username=${username.value}&pwd=${pwd.value}` // 在发送请求之前,设置请求头 设置的叫Content-Type // 请求头一定要在open之后 send之前 xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded') xhr.send(msg) }
-
json
在发送请求之前,设置请求头字段Content-Type, 一定要在open()之后send()之前
传递的数据形式为{x:1,y:2} 不用通过& 但是传递时需要手动转为JSON字符串
后端接收到的数据类型是一个对象
关键代码:
let msg = { username: username.value, pwd: pwd.value } xhr.setRequestHeader('Content-Type', 'application/json') xhr.send(JSON.stringify(msg))
前端结构如下:
<h1>通过post把数据扔给服务器</h1> <hr> <table> <tr> <td>用户名:</td> <td><input type="text" name="username" id="username"></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="pwd" id="pwd"></td> </tr> <tr> <td></td> <td> <button id="btn">POST方式提交</button> </td> </tr> </table>
前端js如下:
const btn = document.querySelector('#btn'); const username = document.querySelector('#username'); const pwd = document.querySelector('#pwd'); let xhr = new XMLHttpRequest(); xhr.onload = () => { console.log(xhr.responseText); } btn.onclick = () => { xhr.open('post', '/postData') // 如果请求体格式为json 就不用通过 x=y&z=s let msg = { username: username.value, pwd: pwd.value } // 设置请求头一定要在open之后 send之前 xhr.setRequestHeader('Content-Type', 'application/json') // 传递时 需要手动转化成JSON字符串 xhr.send(JSON.stringify(msg)) }
-
以上不论以哪种形式传递,传递时都是字符串
- text/plain 后端不会解析成对象
- application/x-www-form-urlencoded 后端解析为对象
- application/json 后端解析为对象 但传递时要手动序列化
4. 表单默认发送请求(非Ajax)
- 表单默认请求的请求类型为document
- 直接表单请求整体网页会刷新
- 请求头格式为x-www-form-urlencoded (不用设置,默认此格式)
前端结构如下:
<h1>表单默认发送请求</h1>
<hr>
<form action="/postData?a=1&b=2" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" id="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="pwd" id="pwd"></td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="非ajax请求"></input>
</td>
</tr>
</table>
</form>
5. 通过FormData传递数据
- form表单有默认的提交刷新页面事件
- onsubmit=‘return false’ 阻止提交默认事件
关键:
-
创建一个FormData容器,直接在请求体中放该容器send(容器)
-
关于容器的数据添加
-
方式一:创建FormData容器,通过append()方法添加
let fd = new FormData() fd.append('username',username.value) fd.append('password',pwd.value) fd.append('id','001')
-
方式二:获取formDOM元素,创建FormData容器将元素添加到FormData中
let formEle = document.querySelector("form") let fd = new FormData(formEle)
-
文件的上传
<input type="file" name="avator" id="avator">
const avator = document.querySelector("#avator")
let fd = new FormData() fd.append("avator", avator.files[0]);
-
-
既可以传递数据 也可以传递文件
前端结构如下:
<form onsubmit="return false">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" id="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="pwd" id="pwd"></td>
</tr>
<tr>
<td>头像: </td>
<td><input type="file" name="avator" id="avator"></td>
</tr>
<tr>
<td></td>
<td>
<button id="btn1">提交1</button>
</td>
</tr>
</table>
</form>
前端js如下:
const username = document.querySelector("#username")
const pwd = document.querySelector("#pwd")
const btn1 = document.querySelector("#btn1")
const avator = document.querySelector("#avator")
const xhr = new XMLHttpRequest();
xhr.onload = () => {
alert(xhr.responseText);
};
btn1.onclick = () => {
// 方式一
// let fd = new FormData();
// fd.append("username",username.value)
// fd.append("pwd",pwd.value)
// fd.append("aaaa",1111)
// fd.append("bbbb",2222)
// 方式二
// let formBox = document.querySelector("form");
// let fd = new FormData(formBox);
// 传文件
const fd = new FormData();
fd.append("uname", username.value);
fd.append("upwd", pwd.value);
fd.append("avator", avator.files[0]);
xhr.open('POST', '/upload');
xhr.send(fd);
}
6. 响应报文
后端响应给前端的东西 格式:xhr.xxx
- 响应行
- status 响应状态码
- statusText 响应状态码描述
- 响应头
- getResponseHeader("XXXXXX") 获取对应字段内容
- getAllResponseHeaders() 获取响应头全部内容
- 响应体
- response 服务器的响应
- responseText 服务器的响应 返回数据的文本
7. 响应JSON
- 在前端设置期望响应的数据类型,期望服务器响应json
xhr.responseType = 'json'
// 当设置响应类型为json后,xhr.responseText不能使用
- 服务端可以设置响应头字段,告诉客户端响应的是JSON数据
let score = [1,2,3]
let scoreJson = JSON.stringify(score)
res.setHeader("Content-Type","application;charset=utf-8")
res.send(scoreJson)
8. 超时处理
- 自动取消请求,设置时间,时间到了数据还没有响应回来
xhr.timeout = 3000
- 手动取消请求
xhr.abort()
9. Ajax中的事件
-
onreadystatechange
- 当ajax请求状态发生变化触发
- readyState === 4 等价于load事件
readyState === 0 : xhr对象已创建或已被abort()方法重置 readyState === 1 : open()方法被调用 readyState === 2 : send()方法被调用 并且响应头和响应状态可获得 readyState === 3 : 下载中,正在解析响应内容 readyState === 4 : 响应内容接收完毕
-
onloadstart
- 开始发送请求触发
- 此时readyState === 1
-
onload
- 数据接收完毕触发
-
onerror
- 请求失败触发 -- 请求发不出去 (404表示请求成功)
-
onprogress
- 接收响应数据时,周期性触发,直到接收完毕
- 传参
e
事件对象 - e.loaded 已经接收的数据
- e.total 总的数据
-
onloadend
- 不论成败 最后都触发
10. 总结
属性 | 含义 |
---|---|
readyState | 表示响应的状态 返回一个数字 |
status | 响应状态码 200 400 等 |
statusText | 响应状态码对应描述 200--OK |
responseXML | 接收格式为XML格式,返回一个document对象 |
responseType | 设置响应内容的类型 |
response | 返回的类型取决responseType的设置 |
responseText | 返回数据的文本 |
timeout | 超时时间 |
方法 | 描述 |
---|---|
open() | 初始化HTTP请求,指定请求方式和URL |
send() | 向服务器发送请求,参数可设置请求体 |
abort() | 若请求已发出,立即终止当前请求 |
setRequestHeader() | 设置HTTP请求头的值,必须在open()之后 |
getResponseHeader() | 返回指定的响应头 |
getAllResponseHeaders() | 返回所有的响应头 |
事件 | 触发条件 |
---|---|
readystatechange | readyState属性值改变触发 |
loadstart | 接收到响应数据时触发 |
load | 请求完成触发 |
error | 请求遇到错误触发 |
progress | 接收到更多数据时,周期性触发 |
loadend | 请求结束触发,无论成败 |
timeout | 预设时间内没有接收到响应触发 |