Ajax

104 阅读6分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

Ajax

Ajax 概述

Ajax 是什么

Ajax 是 Asynchronous Javavascript XML 的缩写,被译为异步 JavaScript 和 XML 。Ajax 本身并不是一个新技术,而是一个在 2005 年被 Jesse James Garrett 提出的新术语,用来描述一种使用现有技术集合的 “新”方法。

当使用 Ajax 模型,HTML 页面能够快速地将数据逐步更新显示在用户界面上,不需要重载(刷新)整个页面。这使得 HMTL 页面能够快速的对用户的操作进行反馈。

尽管 Ajax 中的 “X” 代表 XML ,但由于 JSON 的许多优势,目前 JSON 的使用比 XML 更加普遍。 JSON 和 XML 都被用于在 Ajax 模型中封装数据。

Ajax 涉及的技术

Ajax 只是为实现异步交互的手段,不是一种技术,而是多种技术的整合。其中包括以下几种技术:

  • HTML 页面
  • CSS
  • JavaScript 脚本语言
  • Document Object Model (DOM)
  • XML
  • XMLHttpRequest 对象

上述技术中,XMLHttpRequest 对象是实现 Ajax 异步交互的核心。

Ajax 的核心对象

实现 Ajax 异步交互的核心就是 XMLHttpRequest 对象,该对象为客户端提供了在客户端和服务器之间传输数据的功能。

XMLHttpRequest 对象提供了一个通过 URL 来获取数据的简单方式,并且不会是整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。

XMLHttpRequest 对象最初有微软设计,随后被 Mozilla 、 Apple 和 Google 采纳。如今,该对象已经被 W3C 组织标准化。通过该对象,可以很容易地得到一个 URL 上的资源数据。尽管名字里 XML, 但 XMLHttpRequest 对象可以得到所有类型的数据资源,并不局限于 XML 格式的数据。

实现 Ajax 异步交互

实现 Ajax 的执行步骤

实现 Ajax 异步交互需要服务器逻辑进行配合,而作为客户端的 HTML 页面需要完成以下步骤:

  1. 创建 Ajax 的核心对象 XMLHttpRequest 对象。
  2. 通过 XMLHttpRequest 对象的 open() 方法与服务端建立连接。
  3. 构建请求所需的数据内容,并通过 XMLHttpRequest 对象的 send() 方法发送给服务器端
  4. 通过 XMLHttpRequest 对象提供的 onreadystatechange 事件监听服务器端你的通信状态
  5. 接受并处理服务端向客户端响应的数据结果
  6. 将处理结果更新到 HTML 页面中

创建 XMLHttpRequest 对象。

XMLHttpRequest 对象已经被 W3C 组成进行标准化,但是还是存在 IE 浏览器的兼容问题,不过比较好的就是微软已经放弃了自家的 IE 浏览器,也就说我们几乎已经不用考虑浏览器兼容问题了。

XMLHttpRequest() 构造函数用于初始化一个 XMLHttpRequest 实例对象。在调用下列任何其他方法之前,必须先调用该构造函数,或通过其他方式,得到一个实例对象。

示例代码如下所示

var request = new XMLHttpRequest();

与服务器建立连接

通过 XMLHttpRequest 对象的 open() 方法与服务器建立连接,该方法的语法结构如下所示:

xhrReq.open(method, url, [async][, user][, password]);

参数说明:

  • method: 表示当前的请求方式

    常见的为 GET 和 POST

  • url: 表示当前请求的服务器端地址连接

  • async: 一个可选的布尔参数,表示是否异步执行操作,默认为true

  • user: 可选的用户名用于认证用途;默认为null

  • password: 可选的密码用于认证用途,默认为null

给服务端发送数据

通过 XMLHttpRequest 对象的 send() 方法,将客户端页面的数据发送给服务端,该方法的语法结构如下所示:

xhrReq.send([body])

参数说明:

  • body: 在 XHR 请求中要发送的数据体,如果不传递数据则为 null

绑定 onreadystatechange 事件

onreadystatechange 事件用于监听服务器端的通信状态,该事件监听的依靠是 XMLHttpRequest.readyState 属性,该属性返回一个 XMLHttpRequest 代理当前所处的状态,只要当前属性值被改变,就触发 onreadystatechange 事件。该属性有 5 种状态,如下表所示:

状态描述
0UNSENT代理被创建,但尚未调用 open() 方法。
1OPENEDopen() 方法已经被调用。
2HEADERS_RECEIVEDsend() 方法已经被调用,并且头部和状态已经可获得。
3LOADING正在响应
4DONE响应已完毕

XMLHttpRequest.responseText属性用于接收服务器端的响应结果。

示例代码如下所示:

这里随便找了个 RUL 作为测试

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Ajax的实现步骤</title>
</head>

<body>
<button id="btn">按钮</button>
  <script>
    var btn = document.getElementById('btn')
    btn.addEventListener('click', function () {
        // 1. 实例化 XMLHttpRequest 对象
        var xhrReq = new XMLHttpRequest();
        // 2. 通过 .open() 方法建立连接
        xhrReq.open('GET', 'https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState');
        // 3. 通过 .send() 方法向服务器端发送数据
        xhrReq.send(null);
        // 4. 绑定 onreadystatechange 事件
        xhrReq.onreadystatechange = function () {
          /* .readyState 属性表示当前状态
            值     描述
            0     代理被创建,但尚未调用 open() 方法。
            1     open() 方法已经被调用。
            2     send() 方法已经被调用,并且头部和状态已经可获得。
            3     正在响应
            4     响应已完毕
          */
          if (xhrReq.readyState === 4) {
            console.log(xhrReq.responseText);
          }
   	  }
    })
  </script>
</body>
   
</html>

执行结果如下图所示:

image-20201114093558270.png

实现 Ajax 的异步交互的问题

onreadystatechange 事件的绑定位置

onreadystatechange 事件的绑定位置不同,XMLHttpRequest.readyState 属性的结果也不一样,上面的代码中XMLHttpRequest.readyState 属性的执行结果为

2
3
4

我们如果改一下调用位置的话,其执行结果会怎么样呢?

示例代码如下所示

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>实现 Ajax 异步交互</title>
</head>

<body>
  <button id="btn">按钮</button>
  <script>
    var btn = document.getElementById('btn')
    btn.addEventListener('click', function () {
      var xhrReq = new XMLHttpRequest();
      xhrReq.onreadystatechange = function () {
        /* .readyState 属性表示当前状态
        值 描述
        0 代理被创建,但尚未调用 open() 方法。
        1 open() 方法已经被调用。
        2 send() 方法已经被调用,并且头部和状态已经可获得。
        3 正在响应
        4 响应已完毕
        */
        console.log(xhrReq.readyState);
      }
      xhrReq.open('GET', 'https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState');
      xhrReq.send(null);

    })
  </script>
</body>

</html>

执行结果如下图所示

01_实现Ajax异步交互.gif

从执行结果可以看出,Ajax 的实现步骤并不是只有那一种。

但是为什么没有状态 0 呢?这是因为我们在绑定这个之前必须完成对象的初始化,而状态 0 表示对象未初始化,所以不能得到状态 0。

根据这些状态的不同我们可以完成不同的操作。

send() 方法的问题

如果当前的请求方式为 GET 的话, send() 方法中只能传递 null 值,如果想要添加请求数据的话需要将请求添加地址连接中。

发送数据的格式如下所示

name=value

如果多个数据的话需要使用 & 分隔。

请求方式

GET 请求方式

Ajax 异步交互中使用 GET 请求方式的话,需要注意一下两个问题:

  1. 将构建的请求数据添加到 open() 方法中的 URL 地址中。
  2. 发送请求数据中的 send() 方法中参数设置为 null 值。

POST 请求方式

Ajax 异步交互中如果使用的是 POST 请求的话,需要注意下面两个问题

  1. 调用 send() 方法之前, open() 方法之后,需要通过 XMLHttpRequest 对象的 setRequestHeader() 方法设置请求头信息。

    setRequestHeader() 语法结构如下所示

    xhrReq.setRequestHeader(header, value);
    

    参数说明:

    • header: 属性的名称。
    • value: 属性的值。
  2. 通过 XMLHttpRequest 对象的 send() 方法发送请求数据。

示例代码如下所示

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>POST请求方式</title>
</head>

<body>
  <button id="btn">按钮</button>
  <script>
    var btn = document.getElementById('btn')
    btn.addEventListener('click', function () {
      var xhrReq = new XMLHttpRequest();
      xhrReq.open('POST', 'https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState');
      /*
      在open方法之后 send 之前设置请求头
      xhrReq.setRequestHeader(header, value);
      - header: 属性的名称。
      - value: 属性的值。
      */
      xhrReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')

      xhrReq.send('user=is_sweet&pwd=123456');
    })
  </script>
</body>

</html>

执行结果如下所示

02_POST访问方式.gif