AJAX

一、Ajax 基本介绍

Ajax 的全称是 Asynchronous Javascript And XML(异步 JavaScript 和 XML)

通过 AJAX 可以在浏览器中向服务器发送异步请求,进行数据交互

最大的优势:无刷新获取数据

AJAX 的优点

  • 可以无需刷新页面而与服务器端进行通信(实现局部刷新)
  • 允许根据用户事件来更新部分页面内容

AJAX 的缺点

  • 没有浏览历史,不能回退
  • 存在跨域问题(同源)
  • SEO 不友好

Ajax 的典型应用场景

用户名检测:注册用户时,通过 ajax 的形式,动态检测用户名是否被占用

image-20230504093210686

搜索提示:当输入搜索关键字时,通过 ajax 的形式,动态加载搜索提示列 表image-20230504093251279

数据分页显示:当点击页码值的时候,通过 ajax 的形式,根据页码值动态 刷新表格的数据image-20230504093331555

数据的增删改查:数据的添加、删除、修改、查询操作,都需要通过 ajax 的 形式,来实现数据的交互image-20230504093356633

1、XML

XML 是一种可扩展标记语,被设计用来传输和存储数据。XML 和 HTML 类似,不同的是 HTML 中都是预定义标签,而 XML 中没有预定义标签, 全都是自定义标签,用来表示一些数据。

XML 格式臃肿,和数据无关的代码多,体积大,传输效率低。在 Javascript 中解析 XML 比较麻烦。现已被 JSON 代替

2、JSON

JSON 的英文全称是 JavaScript Object Notation,即“JavaScript 对象。表示法”。简单来讲,JSON 就是 Javascript 对象和数组的字符串表示法,它使用文本表示一个 JS 对象或数组的信息,因此,JSON 的本质是字符

作用:JSON 是一种轻量级的文本数据交换格式,在作用上类似于 XML,专 门用于存储和传输数据,但是 JSON 比 XML 更小、更快、更易解析 现状:JSON 是在 2001 年开始被推广和使用的数据格式,到现今为止,JSON 已经成为了主流的数据交换格式

JSON 的两种结构

JSON 就是用字符串来表示 Javascript 的对象和数组。所以,JSON 中包含 对象和数组两种结构,通过这两种结构的相互嵌套,可以表示各种复杂的数据结构

对象结构:对象结构在 JSON 中表示为 { } 括起来的内容。数据结构为 { key: value, key: value, … } 的键值对结构。其中,key 必须是使用英文 的双引号包裹的字符串,value 的数据类型可以是数字、字符串、布尔值、null、 数组、对象 6 种类型

image-20230504092616262

数组结构:数组结构在 JSON 中表示为 [ ] 括起来的内容。数据结构为 [ “java”, “javascript”, 30, true … ] 。数组中数据的类型同样可以是数字、 字符串、布尔值、null、数组、对象 6 种类型

image-20230504092646601

JSON 语法注意事项

  • 属性名必须使用双引号包裹
  • 字符串类型的值必须使用双引号包裹
  • JSON 中不允许使用单引号表示字符串
  • JSON 中不能写注释
  • JSON 的最外层必须是对象或数组格式
  • 不能使用 undefined 或函数作为 JSON 的值

JSON 和 JS 对象的关系

JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息, 本质是一个字符串

JSON 和 JS 对象的互转

可以使用 JSON.parse()和 JSON.stringify()方法

二、AJAX 的使用

核心对象

XMLHttpRequest,AJAX 的所有操作都是通过该对象进行的

使用步骤

  1. 创建 XMLHttpRequest 对象
1
const xhr = new XMLHttpRequest();

2.设置请求信息

1
2
3
xhr.open(method, url);
//可以设置请求头,一般不设置
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  1. 发送请求
1
xhr.send(body); //get 请求不传 body 参数,只有 post 请求

4.接收响应

1
2
3
4
5
6
7
8
//xhr.responseXML 接收 xml 格式的响应数据
//xhr.responseText 接收文本格式的响应数据
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
const text = xhr.responseText;
console.log(text);
}
};

xhr.readyState 可以用来查看请求当前的状态

0: 表示 XMLHttpRequest 实例已经生成,但是 open()方法还没有被调用。

1: 表示 send()方法还没有被调用,仍然可以使用 setRequestHeader(),设定 HTTP 请求的头信息

2: 表示 send()方法已经执行,并且头信息和状态码已经收到。

3: 表示正在接收服务器传来的 body

4: 表示服务器数据已经完全接收,或者本次接收已经失败了

使用 xhr 对象发起带参数的 GET 请求时,只需在调用 xhr.open 期间,为 URL 地址指定参数即可:

1
xhr.open('GET','http://congtf.top/tags?id=1&title=技术')

这种在 URL 地址后面拼接的参数,叫做查询字符串

GET 请求携带参数的本质

无论使用 $.ajax(),还是使用 $.get(),又或者直接使用 xhr 对象发起 GET 请求,当需要携带参数的时候,本质上,都是直接将参数以查询字符串的形 式,追加到 URL 地址的后面,发送到服务器的

1
2
3
$.get(url, { name: "zs", age: 20 }, function () {});
// 等价于
$.get(url + "?name=zs&age=20", function () {});

三、XMLHttpRequest Level2 的新特性

旧版 XMLHttpRequest 的缺点:

  • 只支持文本数据的传输,无法用来读取和上传文件
  • 传送和接收数据时,没有进度信息,只能提示有没有完成

XMLHttpRequest Level2 的新功能

  • 可以设置 HTTP 请求的时限
  • 可以使用 FormData
  • 可以上传文件
  • 可以获得数据传输的进度信息

1、设置 HTTP 请求时限

有时,Ajax 操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。新版本的 XMLHttpRequest 对象,增加了 timeout 属性,可 以设置 HTTP 请求的时限:

1
xhr.timeout = 3000;

上面的语句,将最长等待时间设为 3000 毫秒。过了这个时限,就自动停止 HTTP 请求。与之配套的还有一个 timeout 事件,用来指定回调函数:

1
2
3
xhr.ontimeout = function () {
alert("请求超时");
};

2、FormData 对象管理表单数据

Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作:

1
2
3
4
5
6
7
8
9
10
11
// 1.新建FormData对象
const fd = new FormData();
// 2.为FormData添加表单项
fd.append("uname", "zs");
fd.append("upwd", "123456");
// 3.创建XHR对象
const xhr = new XMLHttpRequest();
// 4.发请求
xhr.open("POST", "http://congtf.top");
// 5.直接提交FormData对象,这与提交网页表单效果完全一样
xhr.send(fd);

FormData 对象也可以用来获取网页表单的值,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
// 获取表单元素
const form = document.querySelector("#form1");
// 监听表单元素的submit事件
form.addEventListener("submit", function (e) {
e.preventDefault();
// 根据form表单创建FormData对象,会自动将表单数据填充到FormData对象中
const fd = new FormData(form);
const xhr = new XMLHttpRequest();
xhr.open("POST", "http://congtf.top");
xhr.send(fd);
xhr.onreadystatechange = function () {};
});

3、上传文件

新版 XMLHttpRequest 对象,不仅可以发送文本信息,还可以上传文件

实现步骤

  1. 定义 UI 结构

    1
    2
    3
    4
    5
    6
    7
    <!-- 文件选择框 -->
    <input type="file" id="file1" />
    <!-- 上传按钮 -->
    <button id="btnUpload">上传文件</button>
    <br />
    <!-- 显示上传到服务器上的图片 -->
    <img src="" id="img" width="800" />
  2. 验证是否选择了文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    const btnUpload = document.querySelector("#btnUpload");
    btn.addEventListener("click", function () {
    const files = document.querySelector("#file1");
    if (files.length <= 0) {
    return alert("请选择要上传的文件!");
    }
    // 创建FormData对象
    const fd = new FormData();
    // 追加文件
    fd.append("avatar", files[0]);
    // 创建xhr对象
    const xhr = new XMLHttpRequest();
    // 发请求
    xhr.open("POST", "http://congtf.top");
    xhr.send(fd);
    xhr.onreadystatechange = function () {
    if (xhr.state === 4 && xhr.status === 200) {
    const data = JSON.parse(xhr.responseText);
    if (data.status === 200) {
    // 将服务器返回的图片地址设置为img标签的src属性
    document.querySelector("#img").src = "http://congtf.top" + data.url;
    } else {
    // 文件上传失败
    console.log("data.message");
    }
    }
    };
    });
  3. 向 FormData 中追加文件

  4. 使用 xhr 发起上传文件的请求

  5. 监听 onreadystatechange 事件

4、显示文件上传进度

新版本的 XMLHttpRequest 对象中,可以通过监听 xhr.upload.onprogress 事件,来获取到文件的上传进度。语法格式如下:

1
2
3
4
5
6
7
8
9
10
const xhr = new XMLHttpRequest();
// 监听xhr.upload的onprogress事件
xhr.upload.onprogress = function (e) {
// e.lengthComputable是一个布尔值,表示当前上传的资源是否具有可计算的长度
if (e.lengthComputable) {
// e.loaded 表示已传输的字节
// e.total 表示需要传输的总字节
const percentComplete = Math.ceil((e.loaded / e.total) * 100);
}
};

四、axios

axios 是专注于网络数据请求的库

相比于原生的 XMLHttpRequest 对象,axios 简单易用

相比于 jQuery,axios 更加轻量化,只专注于网络数据请求

axios 发起 GET 请求

1
2
3
4
5
6
7
axios
.get(url, {
params: {
/*参数*/
},
})
.then(callback);

示例如下:

1
2
3
4
5
const paramsObj = { name: "zs", age: 20 };
axios.get("http:congtf.top", { params: paramsObj }).then(function (res) {
// axios默认包了一层data,res.data才是服务器返回的数据
const result = res.data;
});

axios 发起 POST 请求示例如下:

1
2
3
4
5
const dataObj = { name: "zs", age: 20 };
axios.post("http:congtf.top", dataObj).then(function (res) {
// axios默认包了一层data,res.data才是服务器返回的数据
const result = res.data;
});

直接使用 axios 发起请求:

1
2
3
4
5
6
7
8
9
10
axios({
method: "请求类型",
url: "请求的url地址",
data: {
/*POST数据*/
},
params: {
/*GET参数*/
},
}).then(callback);

五、同源与跨域、防抖与节流

1、同源策略

如果两个页面的协议,域名和端口都相同,则两个页面具有相同的源

例如,下表给出了相对于 http://www.test.com/index.html (没写端口号默认 是 80)页面的同源检测

image-20230504104555104

同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能 MDN 官方给定的概念:同源策略限制了从同一个源加载的文档或脚本如何与来自 另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制

通俗的理解:浏览器规定,A 网站的 JavaScript 不允许和非同源的网站 C 之间进行资源的交互,例如:

  1. 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
  2. 无法接触非同源网页的 DOM
  3. 无法向非同源地址发送 Ajax 请求

同源指的是两个 URL 的协议、域名、端口一致,反之,则是跨域

出现跨域的根本原因:浏览器的同源策略不允许非同源的 URL 之间进行资源的交互

浏览器对跨域请求的拦截

image-20230504105321422

注意:浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器 拦截,无法被页面获取到!

如何实现跨域数据请求

2、JSONP

出现的早,兼容性好(兼容低版本 IE)。是前端程序员为了解决跨域问题, 被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。

JSONP (JSON with Padding) 是 JSON 的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。

JSONP 的实现原理

由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。 但是在网页中有一些标签天生具有跨域能力,比如:img link iframe script。因此,JSONP 的实现原理,就是通过 script 标签的 src 属性,请求跨
域的数据接口,并通过函数调用的形式,接收跨域接口响应回来的数据。

JSONP 的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 动态的创建一个script标签
const script document.createElement('script')
// 设置script的src,设置回调函数
script.src='http://loacalhost:3000/testAJAX?callback=abc'
function abc(data) {
alert(data.name)
}
// 将script添加到body中
document.body.appendChild(script)
// 服务器中路由的处理
router.get('/testAJAX',function(req,res) {
console.log('收到请求')
const callback = req.query.callback
const obj = {
name:'zs',
age:20
}
res.send(callback+"("+JSON.stringfy(obj)+")")
})

3、CORS

CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方 案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 get 和 post 请求。跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些 源站通过浏览器有权限访问哪些资源

CORS 怎么工作的?

CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应 以后就会对响应放行

CORS 的使用

主要是服务器端的设置:

1
2
3
4
5
router.get("/testAJAX", function (req, res) {
// res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000")
res.set("Access-Control-Allow-Origin", "*");
res.send("返回的相应");
});

4、防抖

防抖策略(debounce)是当事件被触发后,延迟 n 秒后再执行回调,如果 在这 n 秒内事件又被触发,则重新计时

image-20230504111044196

防抖的应用场景

用户在输入框中连续输入一串字符时,可以通过防抖策略,只在输入完后, 才执行查询的请求,这样可以有效减少请求次数,节约请求资源

防抖的基本原理是在一定时间内,将多次触发的函数调用合并为一次调用执行。当用户连续触发事件时,防抖函数会清空之前设定的定时器,并重新设定一个新的定时器来延迟函数的执行。只有当用户停止操作后,在设定的时间内没有再次触发事件,则函数才会被真正地执行一次

实现一个基本的防抖函数步骤如下:

  1. 在函数外部设置一个计时器变量(例如 timeoutId)和函数执行的延迟时间(例如 delay)
  2. 当函数被触发时,清除之前设定的计时器
  3. 重新设定一个计时器,并用它来延迟函数的执行
  4. 如果在设定的延迟时间内再次触发了函数,则回到步骤 2
  5. 如果在设定的延迟时间内没有再次触发函数,计时器会触发执行原始函数

以下是一个基本的防抖函数

1
2
3
4
5
6
7
8
9
10
11
function debounce(func, delay) {
let timeoutId;
return function () {
const context = this;
const args = arguments;
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
func.apply(context, args);
}, delay);
};
}

该函数接受两个参数:要执行的函数以及防抖延迟时间。它返回一个新函数,该函数会在防抖延迟时间内被多次调用时只执行一次原始函数

5、节流

节流策略(throttle),顾名思义,可以减少一段时间内事件的触发频率。

节流的应用场景

  1. 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次
  2. 懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算 的频率,而不必去浪费 CPU 资源

节流阀的概念

高铁卫生间是否被占用,由红绿灯控制,红灯表示被占用,绿灯表示可使用

假设每个人上卫生间都需要花费 5 分钟,则五分钟之内,被占用的卫生间无法被 其他人使用

上一个人使用完毕后,需要将红灯重置为绿灯,表示下一个人可以使用卫生 间

下一个人在上卫生间之前,需要先判断控制灯是否为绿色,来知晓能否上卫 生间

类似的

节流阀为空,表示可以执行下次操作;不为空,表示不能执行下次操作

当前操作执行完,必须将节流阀重置为空,表示可以执行下次操作了

每次执行操作前,必须先判断节流阀是否为空

一个基本的节流函数示例如下:

1
2
3
4
5
6
7
8
9
10
11
function throttle(func, delay) {
let last = 0;
return function (...args) {
const now = +new Date();
if (now - last < delay) {
return;
}
last = now;
func.apply(this, args);
};
}

总结防抖和节流的区别

防抖:如果事件被频繁触发,防抖能保证只有最有一次触发生效!前面 N 多 次的触发都会被忽略!当事件被触发时,函数在固定时间间隔内不被执行,只有事件停止触发后,函数才会执行一次。适用于处理一些不需要连续响应的事件(如输入框输入、按钮点击等),可以避免函数被频繁调用,提高性能和稳定性。

节流:如果事件被频繁触发,节流能够减少事件触发的频率,因此,节流是 有选择性地执行一部分事件!当事件被触发时,函数在固定时间间隔内最多只执行一次。适用于高频率事件(如滚动、窗口调整等),可以防止函数被频繁调用,减少不必要的计算,提高性能和响应速度

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2023-2025 congtianfeng
  • 访问人数: | 浏览次数: