Ajax

Ajax(异步JavaScript和XML,Asynchronous JavaScript And XML),是在浏览器与服务器进行后台数据交换的一种编程方法。其核心是XMLHttpRequest对象的应用,本文将讨论相关应用并封装Ajax类。

XMLHttpRequest对象的常用属性:

  • onreadystatechange属性,指定服务器返回状态改变时的响应函数。
  • readyState属性,表示服务器返回的状态值,4表示成功完成。应注意,服务器返回状态4并不表示正确获取资源,还需要status属性确认。
  • status属性,返回获取资源的状态码。200表示从服务器成功获取新的资源,304表示资源没有变化,可以从缓存中获取资源;这两种状态时都有可用的资源。
  • statusText属性,返回获取资源状态的文本描述。
  • responseText属性,获取的文本内容。
  • responseXML属性,获取的XML数据。

XMLHttpRequest对象中常用的方法:

  • abort()方法,终止向服务器请求的操作。
  • getAllResponseHeaders()方法,获取服务器返回的所有头部信息。
  • getResponseHeader()方法,获取服务器返回的指定名称的头部信息。
  • open()方法,设置求资源的参数。
  • send()方法,向服务器发送请求。
  • setRequestHeader()方法,设置请求时的头部信息。

向服务器请求资源时有两种连接方法,即GET和POST方法,需要通过open()和send()两个方法配合完成。其中,open()方法的参数设置如下:

  • 参数一,指定请求资源的连接方法,即GET或POST。
  • 参数二,指定请求资源的URL地址。GET方法连接时,如果有参数则需要在资源地址的后面添加问号(?)和参数,如"?id=100&flag=101"。
  • 参数三,指定是否异步操作,一般会设置为true,避免在请求资源时造成页面停止响应。
  • 参数四和参数五,如果获取资源需要凭证,则通过这两个参数分别设置用户名和密码。

send()方法的参数,当使用GET方法连接时设置为null,使用POST方法连接时,方法的参数指定获取资源时需要的参数,如“id=100&flag=101”。

下面的代码会创建一个Ajax类,用于获取服务器资源。

HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <div id="result"></div>
    <button type="button" onclick="showList();">载入列表</button>
</body>
</html>
<script>
    class Ajax {
        #url = null;
        #param = "";
        #method = "GET";
        #isAsync = true;
        //
        constructor(url, param = "", method = "GET", isAsync = true) {
            this.#url = url;
            this.#param = param;
            this.#method = method;
            this.#isAsync = isAsync;
        }
        // 获取文本资源
        getText(fn) {
            let xmlHttp = new XMLHttpRequest();
            if (xmlHttp === null) return;
            xmlHttp.onreadystatechange = function () {
                if (xmlHttp.readyState === 4) {
                    if (xmlHttp.status === 200 || xmlHttp.status === 304) {
                        fn(xmlHttp.responseText);
                        xmlHttp = null;
                    }
                }
            };
            //
            if (this.#method === "GET") {
                xmlHttp.open("GET", this.#url + "?" + this.#param, this.#isAsync);
                xmlHttp.send(null);
            } else if (this.#method === "POST") {
                xmlHttp.open("POST", this.#url, this.#isAsync);
                xmlHttp.send(this.#param);
            }
        }
        // 获取XML资源
        getXml(fn) {
            let xmlHttp = new XMLHttpRequest();
            if (xmlHttp === null) return;
            xmlHttp.onreadystatechange = function () {
                if (xmlHttp.readyState === 4) {
                    if (xmlHttp.status === 200 || xmlHttp.status === 304) {
                        fn(xmlHttp.responseXML);
                        xmlHttp = null;
                    }
                }
            };
            //
            if (this.#method === "GET") {
                xmlHttp.open("GET", this.#url + "?" + this.#param, this.#isAsync);
                xmlHttp.send(null);
            } else if (this.#method === "POST") {
                xmlHttp.open("POST", this.#url, this.#isAsync);
                xmlHttp.send(this.#param);
            }
        }
        //
    }
    //
    function showList() {
        new Ajax("list.html").getText(function (txt) {
            document.getElementById("result").innerHTML = txt;
        });
    }
</script>

页面中的JavaScript代码部分,首先创建了Ajax类,其中包含四个私有变量,分别是:

  • #url,指定获取资源的地址。
  • #param,指定获取资源时需要的参数,默认为空字符串。
  • #method,指定获取资源的连接方法,应指定为"GET"或"POST"。
  • #isAsync,指定是否异步操作。

constructor()构造函数同样包括四个参数,分别指定资源地址、参数、连接方法和是否异步操作。

接下来是getText()方法,用于获取文本资源,其参数为函数类型,用于处理获取的文本资源。onreadystatechange事件中指定了一个匿名函数进行处理,函数中,当状态指示为获取了可用资源时,调用方法参数指定的函数进行处理,处理函数由参数带入xmlHttp对象的responseText属性获取的文本信息。方法的最后,分别根据GET和POST连接方法发送获取资源的请求。

Ajax类的最后定义的是getXml()方法,其中,除了使用responseXML属性获取XML数据以外,其它操作代码完全相同。

页面中,使用id为"result"的div元素显示获取的文本内容,在“载入列表”按钮的onclick事件响应函数中,使用如下代码请求服务资源。

JavaScript
function showList() {
        new Ajax("list.html").getText(function (txt) {
            document.getElementById("result").innerHTML = txt;
        });
    }

代码中,指定资源为当前页面相同路径的list.html文件,读取文件内容后,通过innerHTML属性将文本内容添加到result元素中,获取的文本信息会解析为页面中的HTML元素。下面的代码,准备了包含十条内容的列表代码,可以复制到list.html文件中测试使用。

HTML
<ul id='list1' class='list_res'>
    <li><a href='/article/Article.aspx?id=a251000' target='_blank'>Excel与数据处理——概述</a></li>
    <li><a href='/article/Article.aspx?id=a251001' target='_blank'>Excel和二维表结构</a></li>
    <li><a href='/article/Article.aspx?id=a251002' target='_blank'>小小单元格有大学问</a></li>
    <li><a href='/article/Article.aspx?id=a251003' target='_blank'>区域</a></li>
    <li><a href='/article/Article.aspx?id=a251004' target='_blank'>公式与函数</a></li>
    <li><a href='/article/Article.aspx?id=a251005' target='_blank'>数字与计算</a></li>
    <li><a href='/article/Article.aspx?id=a251006' target='_blank'>文本</a></li>
    <li><a href='/article/Article.aspx?id=a251007' target='_blank'>长数字、前导0与自动填充</a></li>
    <li><a href='/article/Article.aspx?id=a251008' target='_blank'>日期与时间</a></li>
    <li><a href='/article/Article.aspx?id=a251009' target='_blank'>逻辑运算与条件判断</a></li>
</ul>

测试无误后,可以将Ajax类的代码保存到网站/js/ajax.js文件,以便重复使用;在需要使用Ajax类的页面中,可以参考如下代码使用。

HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <div id="result"></div>
    <button type="button" onclick="showList();">载入列表</button>
</body>
</html>
<script src="/js/ajax.js"></script>
<script>
    function showList() {
        new Ajax("list.html").getText(function (txt) {
            document.getElementById("result").innerHTML = txt;
        });
    }
</script>