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的语法:
<name>小明</name>
<age>29</age>
<sex>男</sex>以上的代码中,标签的名字会作为数据的"key"标签中间的内容会作为value传输给后端
和HTML的区别:
HTML用于在浏览器中渲染内容,进行内容的呈现
HTML的标签名字自己定义没有效果
二、AJAX 的使用
2.1 核心
Ajax 的核心是XMLHttpRequest 对象。XMLHttpRequest对象提供了在客户端和服务端传输数据的功能,XMLHttpRequest 对象提供了通过 URL 方式来获取数据,只更新网页的一部分数据。
2.2 实现 ajax 的步骤
创建 Ajax 核心对象(XMLHttpRequest)
const xhr = new XMLHttpRequest();
通过 Ajax 核心对象的 open() 方法建立与服务端的链接
xhr.open("get","url",true);
构建请求的数据内容,通过 Ajax 核心对象的 send() 方法发送给服务端
xhr.send();
通过 Ajax 核心对象提供的 onreadystatechange 事件,监听服务端的通信状态
接受处理服务端响应的结果
将结果更新到页
(1)创建 XMLHttpRequest 对象
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
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 了
xhr.onreadystatechange = function(){
// 每次 readyState 改变的时候都会触发该事件
// 我们就在这里判断 readyState 的值是不是到 4
// 并且 http 的状态码是不是 200
if (xhr.readyState === 4){
if(xhr.status===200){
// 这里表示验证通过
// 我们就可以获取服务端给我们响应的内容了
console.log(xhr.responseText)
}
}
}(7)ajax四步走
// 第一步:创建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 请求
get请求传递参数 是 使用 queryString 的方式
就是直接拼接在请求接口地址后面
直接在地址后面加一个 ?,然后以 key=value 的形式传递、
多个参数使用&进行连接
xxxx.com?key=value&key=value&key=value
// 创建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')方法 设定请求头
携带的参数 按照 queryString 的格式 传递,请求头这样设定
value 应当设定为 'application/x-www-form-urlencoded'
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
发送服务器的传参格式
xhr.send('username=lbw&password=555');
携带的参数 按照 json 的格式 传递,请求头 这样设定
value 应当设定为 'application/json'
xhr.setRequestHeader('content-type','application/json');
json 的 传参格式
// let o = {
// username:'lbw',
// password:555
// }
// xhr.send(JSON.stringify(o)); 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 同源策略
同域名
同协议
同端口
这三个只要任何一个不满足,就是跨域了
//客户端 服务端
"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)后端响应头允许跨域(熟记)
'Access-Control-Allow-Origin': '*'(3)解决跨域的方案
浏览器插件
1.Allow Cros插件
一定不能使用file协议打开文件,使用open with live server,保证在appache的环境下运行html
2.谷歌命令
在有请求头的情况下,谷歌插件不能解决跨域问题
步骤
- 右键谷歌浏览器图标
- 点击快捷方式
- 在起始位置一栏,添加如下代码
--user-data-dir=C:\chromedata注意:--前面有一个空格
3. JSONP(需要服务器)
jsonp是我们实现跨域请求的手段,是把我们之前的东西组合在一起使用的技术手段而已
利用的是 script 标签来实现script 标签的本质
浏览器给我们提供了一个 script 标签
它的本质就是请求一个外部资源,是不受到同源策略的影响的
同时 script 标签的 src 属性,也是一种请求,也能被服务器接收到
jsonp只能发起get请求
script标签的src属性请求回来的东西是一个字符串,浏览器会把这个字符串当作 js 代码来执行
所以我们就可以利用这个 script 标签的 src 属性来进行跨域请求了
操作步骤:
动态生成一个script标签
let sc=document.createElement('script')给script标签的src属性添加api接口
sc.src="http://..........?key=value&key1=value1"src中api接口最后添加上
&callback=cb回调函数声明回调函数
cb(),所有请求功能都在cb()里完成把script添加至body中
document.body.append(sc)
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);