Skip to content

AJAX

一、概念

1.1 什么是AJAX

  • ajax 即 Asynchronous Javascript And XML(异步JavaScript和XML)。

  • 是 前后端数据交互的一种技术,用于快速创建动态网页的技术。

  • 它是异步的AJAX 通过在后台与服务器进行少量数据交换,使网页实现异步更新。这意味着可以在不重载整个页面的情况下,对网页的某些部分(局部)进行更新。

  • 传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个页面。

1.2 说明

Ajax 并不是一个新技术,而是多个技术的整合:

HTML,CSS,JavaScript,DOM,XML,XML,HttpRequest 对象

1.3 传统ajax的优劣

  • 不需要插件的支持,原生 js 就可以使用

  • 只更新局部,而不用刷新整个页面

  • 它是异步的,无阻塞的

  • 流程比较多,编写比较麻烦

1.4 什么是异步

javascript是单线程

javascript的执行顺序是从上到下的,异步阻塞的意思是,执行到异步逻辑的时候,会将异步逻辑添加到js的任务队列,继续执行javascript主线程的逻辑,等到任务队列中返回结果,才进行回调

比如:中午去买饭,要排队,一个人买完之后才到下一个人,但是前面那个人付钱的时候,手机死机卡住了

=>同步: 后面的人一直等,等到他手机开机,并且付完钱,才到下一个人​

=>异步: 手机死机了,到旁边去,让下一个人继续买房,一直到手机恢复了,再付钱

同步是阻塞的

异步是无阻塞的

setTimeout 和 setInterval都是异步的

1.5 了解XML

ajax基于XMLHttpRequest是一种扩展的标记语言,和HTML是不一样的,HTML是用来展示视图用,XML是用来前后端数据传输的一种标记语言

比如 XML的语法:

html
<name>小明</name>
<age>29</age>
<sex>男</sex>

以上的代码中,标签的名字会作为数据的"key"标签中间的内容会作为value传输给后端

  • 和HTML的区别:

  • HTML用于在浏览器中渲染内容,进行内容的呈现

  • HTML的标签名字自己定义没有效果

二、AJAX 的使用

2.1 核心

Ajax 的核心是XMLHttpRequest 对象。XMLHttpRequest对象提供了在客户端和服务端传输数据的功能,XMLHttpRequest 对象提供了通过 URL 方式来获取数据,只更新网页的一部分数据。

2.2 实现 ajax 的步骤

  1. 创建 Ajax 核心对象(XMLHttpRequest)

  2. const xhr = new XMLHttpRequest();

  3. 通过 Ajax 核心对象的 open() 方法建立与服务端的链接

  4. xhr.open("get","url",true);

  5. 构建请求的数据内容,通过 Ajax 核心对象的 send() 方法发送给服务端

  6. xhr.send();

  7. 通过 Ajax 核心对象提供的 onreadystatechange 事件,监听服务端的通信状态

  8. 接受处理服务端响应的结果

  9. 将结果更新到页

(1)创建 XMLHttpRequest 对象

js
const xhr = new XMLHttpRequest();
// 在 IE 中又分为两种情况:可以不考虑
// IE7 版本:new ActiveXObject("Msxml2.XMLHTTP")
// IE6 及以下版本:new ActiveXObject("Microsoft.XMLHTTP")

(2)向服务器发送请求

如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法

open(method,url,async)规定请求的类型、URL 以及是否异步处理请求--打开与服务器的连接

  • method:请求的类型;GET 或 POST

  • url:请求数据的url地址--接口

  • async:true(异步)或 false(同步)----默认是true

js
xhr.open("get","./data.php",true);

send()方法将请求发送到服务器

  • 在 Ajax 提交方式中如果使用 get 方式提交数据时,send 方法中 不传参数 或 写入null。

  • 在 Ajax 提交方式中如果使用 post 方式提交数据时,send 方法中 传入参数。

xhr.send();

(3)ajax 的状态信息 - readyState

Ajax 核心对象的 readyState属性 存有 XMLHttpRequest 的状态信息。从 0 到 4 发生变化。

  • 0 请求未初始化,也就是 open 方法还没有执行

  • 1 服务器连接已建立,表示配置信息已经完成,服务器连接已经建立,也就是执行完 open 之后

  • 2 请求已接收,表示 send 方法已经执行完成

  • 3 请求处理中,表示正在解析响应内容

  • 4 请求已完成,且响应已就绪,表示响应内容已经解析完毕,可以在客户端使用了

注意:所以只有当 readyState === 4 的时候,我们才可以正常使用服务端给我们的数据

(4)ajax 的 http状态码 - status

Ajax 核心对象的 status属性 会记录 请求的状态码

  • 200 请求成功

  • 304 请求的资源未变化(没有改动)

  • 404 服务器端地址未找到

  • 注意:当 readyState 等于 4 且状态为 200 时,表示响应已完全就绪:

(5)响应结果 - responseText

Ajax 核心对象的 responseText 属性 会接收服务端对该请求的响应结果(纯文本内容)

(6)onreadystatechange事件

  • 当请求被发送到服务器时,我们需要执行一些基于响应的任务。

  • 在 Ajax 核心对象中有一个事件,叫做 onreadystatechange事件

  • 这个事件是专门用来监听 ajax 对象的 readyState 值改变的的行为

  • 也就是说只要 readyState 的值发生变化了,那么就会触发该事件

  • 所以我们就在这个事件中来监听 ajax 的 readyState 是不是到 4 了

javascript
xhr.onreadystatechange = function(){
    // 每次 readyState 改变的时候都会触发该事件
    // 我们就在这里判断 readyState 的值是不是到 4
    // 并且 http 的状态码是不是 200
    if (xhr.readyState === 4){
        if(xhr.status===200){
            // 这里表示验证通过
            // 我们就可以获取服务端给我们响应的内容了
            console.log(xhr.responseText)
        }
    }
}

(7)ajax四步走

js
// 第一步:创建ajax对象
const xhr = new XMLHttpRequest();
// 第二步:链接到服务器
xhr.open("get","./data.php",true);
// 第三步:发送请求
xhr.send();
// 第四步:监听ajax状态
xhr.onreadystatechange = function(){
    if (xhr.readyState === 4){
        if(xhr.status===200){
            console.log(xhr.responseText);
            //处理返回数据
        }
    }
}

2.3 发送请求时携带参数

  • 我们使用 ajax 发送请求也是可以携带参数的

  • 参数就是和后台交互的时候给他的一些信息

  • 但是携带参数 get 和 post 两个方式还是有区别的

(1)带有参数的 get 请求

  1. get请求传递参数 是 使用 queryString 的方式

  2. 就是直接拼接在请求接口地址后面

  3. 直接在地址后面加一个 ?,然后以 key=value 的形式传递、

  4. 多个参数使用&进行连接

  5. xxxx.com?key=value&key=value&key=value

js
// 创建ajax对象
const xhr = new XMLHttpRequest()

xhr.open('get','./data.php?a=100&b=200',true);

// 发送请求--发送数据给服务器
    // get请求 send(null)
    // post请求才需要在这里传递参数
xhr.send(null);

// 监听ajax状态
xhr.onreadystatechange = function(){
    if (xhr.readyState === 4){
        if(xhr.status===200){
            console.log(xhr.responseText);
            //处理返回数据
        }
    }
}

(2)带有参数的 post 请求

  • post请求使用send来发送数据给服务端,一定要在send方法调用之前设定请求头

  • 通过 ajax核心对象的 xhr.setRequestHeader('key','value')方法 设定请求头

  1. 携带的参数 按照 queryString 的格式 传递,请求头这样设定

  2. value 应当设定为 'application/x-www-form-urlencoded'

  3. xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');

  4. 发送服务器的传参格式

  5. xhr.send('username=lbw&password=555');

  6. 携带的参数 按照 json 的格式 传递,请求头 这样设定

  7. value 应当设定为 'application/json'

  8. xhr.setRequestHeader('content-type','application/json');

json 的 传参格式

js
// let o = {
//     username:'lbw',
//     password:555
// }
// xhr.send(JSON.stringify(o));
js
 const xhr = new XMLHttpRequest();
// 和服务器建立连接
xhr.open('get','./data.php',true);

// post请求使用send来发送数据给服务端,一定要在send方法调用之前设定请求头
	// 传递的数据格式--分请求头
	// 通过ajax对象的setRequestHeader设置请求头
	// xhr.setRequestHeader('key','value')	

		//1. content-type:application/x-www-form-urlencoded;
			// 这个请求头是表单提交数据的格式:和queryString差不多
			// 'a=100&b=200'
		xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
		xhr.send('a=100&b=200');

        //2. content-type:application/json
			// 这个是传递JSON格式  
			// '{"a":"100","b":"200"}'
		xhr.setRequestHeader('content-type','application/json');
		xhr.send('{"a":"100","b":"200"}');

// 监听ajax状态
xhr.onreadystatechange = function(){
  	if (xhr.readyState === 4){
        if(xhr.status===200){
            console.log(xhr.responseText);
            //处理返回数据
   		}
  	}
}

三、同源策略和跨域

3.1 同源策略

  1. 同域名

  2. 同协议

  3. 同端口

这三个只要任何一个不满足,就是跨域了

js
//客户端                  服务端
"http://localhost"=>请求 "http://localhost:3000" 是否跨域? 跨域,因为端口不同
"http://localhost"=>请求 "https://localhost" 是否跨域? 跨域,因为协议不同
"http://localhost"=>请求 "https://chst.vip" 域名不同
"http://chst.vip:80"=>请求"http//chst.vip/abc" 不跨域

3.2 跨域

(1)什么是跨域?

跨域是浏览器的安全策略,服务端根本不存在跨域一说,只有在浏览器里面才有这个限制

只要不同源,就会引起跨域

(2)后端响应头允许跨域(熟记)

js
'Access-Control-Allow-Origin': '*'

(3)解决跨域的方案

浏览器插件
1.Allow Cros插件

​ 一定不能使用file协议打开文件,使用open with live server,保证在appache的环境下运行html

2.谷歌命令

在有请求头的情况下,谷歌插件不能解决跨域问题

步骤

  1. 右键谷歌浏览器图标
  2. 点击快捷方式
  3. 在起始位置一栏,添加如下代码
js
--user-data-dir=C:\chromedata

注意:--前面有一个空格

3. JSONP(需要服务器)
  • jsonp是我们实现跨域请求的手段,是把我们之前的东西组合在一起使用的技术手段而已

  • 利用的是 script 标签来实现script 标签的本质

  • 浏览器给我们提供了一个 script 标签

  • 它的本质就是请求一个外部资源,是不受到同源策略的影响的

  • 同时 script 标签的 src 属性,也是一种请求,也能被服务器接收到

  • jsonp只能发起get请求

  • script标签的src属性请求回来的东西是一个字符串,浏览器会把这个字符串当作 js 代码来执行

  • 所以我们就可以利用这个 script 标签的 src 属性来进行跨域请求了

操作步骤:

  1. 动态生成一个script标签 let sc=document.createElement('script')

  2. 给script标签的src属性添加api接口 sc.src="http://..........?key=value&key1=value1"

  3. src中api接口最后添加上&callback=cb回调函数

  4. 声明回调函数cb(),所有请求功能都在cb()里完成

  5. 把script添加至body中document.body.append(sc)

js
let sc = document.createElement('script');
sc.src = 'https://www.baidu.com/sugrec?prod=pc&wd=手机&cb=cb';

function cb(data){
	//data即请求回来的数据
	console.log(data);
}
document.body.appendChild(sc);

MIT Licensed