ajax
1.概念
AJAX早期主要用来实现异步刷新页面的功能。它的全称是**Asynchronous JavaScript and XML **
**Asynchronous:**翻译成中文是异步的意思,当发送数据请求时,程序不必停下来等待响应。它可以继续运行,等待响应收到时触发事件。通过使用回调来管理这种过程,程序能够以有效的方式运行,避免了数据来回传输带来的延迟。
**JavaScript:**利用 JavaScript 我们可以接收来自服务器端返回的数据,并将这些数据实时的更新到页面上。
**XML:**最开始术语 Ajax 被创造时,经常用 XML 文档来返回数据。但是实际上可以发送许多不同类型的数据。到目前为止,在 Ajax 中最常用的是 JSON,它比 XML 更轻量且更易于解析。JSON 还具备被 JavaScript 原生支持的优点,所以我们可以处理 JavaScript 对象,而不必使用 DOM 方法来解析 XML 文件。
2.优点
- 页面无刷新,在页面内与服务器通信,减少用户等待的时间,增强了用户体验。
- 使用异步方式与服务器通信,响应速度快。
- 可以把一些原本服务器的工作转接到客户端,利用客户端闲置的能力来处理,减轻了服务器和宽带的负担,节约空间和宽带租用成本。
- 基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。
3.缺点
- 无法进行操作的后退,即不支持浏览器的页面后退。
- 对搜索引擎的支持比较弱。
- 可能会影响程序中的异常处理机制。
- 安全问题。对一些网站的攻击,如 CSRF,XXS,SQL 注入等不能很好的防御。
4.应用场景
- 按需获取数据
- 对用户数据校验
- 自动更新页面内容
- 提升用户体验,无刷新的体验
5.原生AJAX实现步骤
-
创建XMLHttpRequest对象
-
发出HTTP请求
<script> //1.创建XHR对象 let xhr = new XMLHttpRequest(); //2.处理服务器响应的事件 xhr.onreadystatechange = function(){ //一共有五个状态,一般关注4状态就是请求成功的意思 if(xhr.readyState == 4 && xhr.status == 200){ //你向ajax后台的程序发送xmlhttp请求的时候, 后台程序接到请求会进行处理,处理结束后,可以返回一串数据给前台,这个就是responseText. let text = xhr.responseText; console.log("服务器响应数据:",text); } } //3.打开连接 //.open("请求方法:get或post","请求路径","同步(false)或异步(true)") xhr.open("get","/getdata"); // 4.发送请求 xhr.send(); </script>
-
接收服务器传回的数据
-
更新网页数据
6.兼容性问题
- 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");
}
7..open(method,url,同或异)
- method: 要使用的HTTP方法。
- 比如GET、POST、PUT、DELETE等。
- url: 要向其发送请求的url地址,字符串格式。
- 同步或者异步:同步是flase异步是true,默认是异步
// 2.打开连接
// get方式:可在地址后面追加信息,多条用&连接
// post方式,必须通过send方法进行传递数据
xhr.open("get","https://jsonplaceholder.typicode.com/users?id=1");
xhr.open("post","https://jsonplaceholder.typicode.com/users");
同步执行,代码会卡在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");
复制代码
8..sent(body)
-
body: 在XHR请求中要发送的数据体,根据请求头中的类型进行传参。
-
如果是GET方法,无需设置数据体,可以传null或者不传参。
// 3.执行发送动作 // get方式 // xhr.send(null); // post方式 xhr.send("name=mh&age=18");
-
send()方法传递值时的三种写法
// 第一种方法
// 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
}));
9..setRequestHeader(header,value)
- 此方法必须在 open() 方法和 send() 之间调用
- header: 一般设置"Content-Type",传输数据类型,即:服务器需要我们传送的数据类型。
- value: 具体的数据类型,常用"application/x-www-form-urlencoded"和"application/json"。
// 设置响应头
// get方式不用设置,而post必须设置
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
10.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);
}
}
11.体验ajax
- 使用 jQuery 中封装的 Ajax,快速体验带来.
- 免费接口:jsonplaceholder.typicode.com/
12.封装ajax函数
//严禁封装
<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>
//普通封装
function ajax(method, url,data, success) {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
success(JSON.parse(xhr.responseText));
}
}
xhr.open(method, url);
xhr.send(data);
}
ajax("get","/getdata",{
name:"za",
age:14
},function (a) {
console.log(a);
});
//对象封装
function ajax(config){
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
let text = JSON.parse(xhr.responseText);
// config.success(text);
success(text);
}
}
xhr.open(config.type,config.url,config.async);
xhr.send(config.data);
}
//Promise分装
function ajax(config){
return new Promise(function(resolve){
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
let text = JSON.parse(xhr.responseText);
// config.success(text);
resolve(text);
}
}
xhr.open(config.type,config.url,config.async);
xhr.send(config.data);
});
}