一、理解AJAX
1.1 AJAX是什么?
AJAX是英文Asynchronous JavaScript and XML 的缩写,含义是异步JavaScript与XML。
1.2 AJAX主要实现什么功能
该技术主要实现客户与服务器的异步通信,实现页面的部分刷新。AJAX可以在不刷新整个页面的情况下用JavaScript操作DOM以实现页面动态更新。
1.3 AJAX相关的技术
1.3.1 XML与XSL
XML(eXtendsible Markup Language):可扩展的标记语言
- XML 指可扩展标记语言(EXtensible Markup Language)
- XML 是一种标记语言,很类似 HTML
- XML 的设计宗旨是传输数据,而非显示数据
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
- XML 是 W3C 的推荐标准
- 没有任何行为的 XML , XML 是不作为的。
也许这有点难以理解,但是 XML 不会做任何事情。XML 被设计用来结构化、存储以及传输信息。
下面是 John 写给 George 的便签,存储为 XML:
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
上面的这条便签具有自我描述性。它拥有标题以及留言,同时包含了发送者和接受者的信息。
但是,这个 XML 文档仍然没有做任何事情。它仅仅是包装在 XML 标签中的纯粹的信息。我们需要编写软件或者程序,才能传送、接收和显示出这个文档。
- XML 仅仅是纯文本
- XML 不是对 HTML 的替代
XML 是对 HTML 的补充。
XML 不会替代 HTML,理解这一点很重要。在大多数 web 应用程 序中,XML 用于传输数据,而 HTML 用于格式化并显示数据。
对 XML 最好的描述是:
XML 是独立于软件和硬件的信息传输工具。
XSL(eXtendsible Stylesheet Language):可扩展的样式单语言,它是一种用来转换XML文档结构的语言。使用XSL可以从一个XML文档中提取数据,并使用该信息创建另一个XML文档。
1.3.2 XMLHttpRequest
XMLHttpRequest是浏览器中定义的对象,它是AJAX技术中的核心对象。 通过JavaScript脚本可以创建XMLHttpRequest 对象。XMLHttpRequest 对象定义了若干属性和方法,通过这些方法和属性就可以向服务器发出异步请求和处理响应结果。
二、XMLHttpRequest 对象
2.1 创建XMLHttpRequest对象
var xmlHttp;
function createXMLHttpRequest(){
if(window.XMLHttpRequest){
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xmlHttp = new XMLHttpRequest();
}else{
// IE6, IE5 浏览器执行代码
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
2.2 XMLHttpRequest 的属性
属性名 | 说明 |
---|---|
onreadystatechange | 为异步请求设置事件处理程序。每当XMLHttpRequest对象的状态改变时都会触发这个事件处理器,通常会调用一个JavaScript函数 |
readState | 该属性表示请求的状态。它可以有下面几个不同的值:0:未初始化;1:正在加载;2:已加载;3:交互中;4:完成 |
responseText | 检索服务器响应,并表示为文本 |
responseXML | 检索服务器响应,并表示为XML DOM对象 |
status | 检索服务器的HTTP状态码。如404 表示Not Found,200表示OK |
statusText | 检索服务器的HTTP状态码的文本; |
responseBody | 检索响应体。该属性是IE7及以后版本的window对象,但不是W3C的规范 |
2.3 XMLRequest 的方法
方法名 | 说明 |
---|---|
abort() | 取消当前HTTP请求 |
getAllResponseHeaders() | 返回所有的请求头。如果 readyState 属性的值不是 3或4,将返回 null。 |
getResponseHeader() | 返回指定的响应头。如果 readyState 属性的值不是 3或4,将返回 null。 |
open(method,url,async) | 规定请求的类型、URL 以及是否异步处理请求。method:请求的类型;GET 或 POST ;url:文件在服务器上的位置;async:true(异步)或 false(同步) |
send() | 发送 HTTP 请求,使用传递给 open() 方法的参数,以及传递给该方法的可选请求体。 |
setRequestHeader() | 向一个打开但未发送的请求设置或添加一个 HTTP 请求。 |
2.4 一个简单的示例
simpleRequest.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Simple XMLHttpRequest</title>
<script type="text/javascript">
var xmlHttp;
function createXMLHttpRequest() {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
function startRequest() {
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET", "simpleResponse.xml", "true");
xmlHttp.send(null);
}
function handleStateChange() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
alert("服务器返回:" + xmlHttp.responseText);
}
}
}
</script>
</head>
<body>
<form action="#">
<input type="button" value="开始异步请求" onclick="startRequest();"/>
</form>
</body>
</html>
simpleResponse.xml
Hello from the server!
2.5 AJAX 的交互模式
- 客户触发事件
<input type="button" value="开始异步请求"
onclick="startRequest();"/>
这里,当用户点击按钮时,将触发onclick事件,程序调用startRequest()函数。
- 创建XMLHttpRequest 对象
在startReques()函数中调用createXMLHttpRequest()函数创建了XMLHttpRequest对象
var xmlHttp;
function createXMLHttpRequest() {
if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
- 向服务器发出请求
在向服务器发出请求之前,应该通过XMLHttpRequest 对象的 onreadystatechange 属性设置回调函数。当XMLHttpRequest 对象的内部状态改变时就会调用回调函数,因此回调函数是处理响应的地方。
function startRequest() {
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET", "simpleResponse.xml", "true");//打开一个HTTP请求,请求的HTTP方法为GET,请求的资源是simpleResponse.xml,并且为异步请求
xmlHttp.send(null);
}
接下来调用XMLHttpRequest 对象的open() 打开一个HTTP请求,在该方法中需要指定请求的HTTP方法(GET方法或者POST方法)以及请求的资源。请求的资源可以是动态资源,如Servlet、CGI脚本或者任何服务器技术等。
调用XMLHttpRequest 对象的**send()**将请求发送到指定的目标资源,send()接受一个参数,通常是一个字符串或DOM对象。这个参数作为请求体的一部分发送到目标URL。当向send()提供参数时,要确保open()中指定的HTTP方法为POST。如果使用POST方法,则需要设置XMLHttpRequest 对象的Content-Type首部,如下所示:
xmlHttp.setRequestHeader("Conetnt-Type","application/x-www-form-urllencoded");
//如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。
如果没有数据作为请求体的一部分发送,该参数应指定为null。
- 服务器处理请求并返回响应
如果请求的是静态资源,服务器将返回该资源。如果请求的是动态资源,服务器将执行动态资源,这可能需要访问数据库甚至另一个系统,然后向用户返回响应。
XMLHttpRequest对象提供两个访问服务器响应的属性。一个属性是responseText,它将响应提供一个字符串。另一个属性是responseXML,它将响应提供为一个XML对象。
//使用responseText属性来访问服务器响应
function handleStateChange() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
alert("服务器返回:" + xmlHttp.responseText);
}
}
}
由于XMLHttpRequest 对象只能处理text/html类型的结果,所以如果请求的是动态资源(如Servlet),需要将Content-Type响应头设置为text/xml,另外,为了避免浏览器在本地缓存结果,需将Cache-Control响应头设置为 no-cache,如下所示:
response.setHeader("Cache-Control","no-cache");
- 通过回调函数处理结果
通过 回调函数可以对响应结果进行处理。在回调函数中首先应该检查XMLHttpRequest 对象的redyState 属性和status 属性的值。当readyState 属性值为4、status 属性的值为200 时表示响应完成,这时才能使用XMLHttpRequest 对象的responseText 或 response XML 检索请求结果。
//回调函数
function handleStateChange() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
alert("服务器返回:" + xmlHttp.responseText);
}
}
}
- 更新HTML DOM 对象
客户使用新的数据更新HTML DOM 页面表示元素。JavaScript脚本可以使用DOM API 获得 HTML 的每个元素的引用。一般方法是使用document.getElementById(“userIdMessage”),这里,userIdMessage 是HTML 文档的一个元素的id属性值。有了元素的引用,JavaScript就可以修改元素的属性、修改元素的style属性或者添加、删除、修改子元素。修改元素内容的一个常用方法是设置元素的innerHTML 属性值。
2.6 使用 innerHTML 属性创建动态内容
innerHTML 属性是一个简单的字符串,表示一组开始标签和结束标签之间的内容。
- 举例:
innerHTML.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>学生查询</title>
<script type="text/javascript">
var xmlHttp;
function createXMLHttpRequest() {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
function startRequest() {
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET", "innerHTML.xml", "true");
xmlHttp.send(null);
}
function handleStateChange() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
document.getElementById("results").innerHTML = xmlHttp.responseText;
}
}
}
</script>
</head>
<body>
<form action="#">
<input type="button" value="查询学生" onclick="startRequest();"/>
<div id="results"></div>
</form>
</body>
</html>
innerHTML.xml
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<table border="1">
<tbody>
<tr><td>学号</td><td>姓名</td><td>性别</td><td>年龄</td>
</tr>
<tr><td>1001</td><td>张三</td><td>男</td><td>19</td>
</tr>
<tr><td>1002</td><td>李四</td><td>女</td><td>24</td>
</tr>
<tr><td>1003</td><td>王五</td><td>男</td><td>23</td>
</tr>
</tbody>
</table>
点击“查询学生按钮”,运行结果如下:
三、DOM 和JavaScript
3.1 DOM的概念
DOM(Document Object Model)指的是文档对象模型,它是W3C的一个规范,可以用一种独立平台和语言的方式访问和修改文档的内容和结构。DOM是面向HTML 和XML 文档的API,为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。文档中的每个元素都是DOM的一部分。在HTML页面通常使用JavaScript 脚本语言来访问DOM。
一个web页面是一个文档。这个文档可以在浏览器窗口或作为HTML源码显示出来。但上述两个情况中都是同一份文档。文档对象模型(DOM)提供了对同一份文档的另一种表现,存储和操作的方式。 DOM是web页面的完全的面向对象表述,它能够使用如 JavaScript等脚本语言进行修改。
3.2 DOM 与 JavaScript
DOM 与JavaScript 很容易混淆。DOM是面向HTML 和XML 文档的API,为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。
人们一般使用JavaScript代码,通过 **DOM 来访问文档和其中的元素。**DOM 并不是一个编程语言,但如果没有DOM, JavaScript 语言也不会有任何网页,XML页面以及涉及到的元素的概念或模型。在文档中的每个元素— 包括整个文档,文档头部, 文档中的表格,表头,表格中的文本都是文档所属于的文档对象模型(DOM)的一部分,因此它们可以使用DOM和一个脚本语言如 JavaScript,来访问和处理。
开始的时候,JavaScript和DOM是交织在一起的,但它们最终演变成了两个独立的实体。JavaScript可以访问和操作存储在DOM中的内容,因此我们可以写成这个近似的等式:
API (web 或 XML 页面) = DOM + JS (脚本语言)
DOM 被设计成与特定编程语言相独立,使文档的结构化表述可以通过单一,一致的API获得,DOM 也可以使用除JavaScript以外的其他的语言来实现。
用于处理XML文档的DOM元素属性
属性名 | 说明 |
---|---|
chilNodes | 返回当前元素所有子元素的数组 |
firstChild | 返回当前元素的第一个下级子元素 |
lastChild | 返回当前元素的最后一个子元素 |
nextSibling | 返回紧跟在当前元素后面的元素 |
previousSibling | 返回紧邻当前元素之前的元素 |
nodeValue | 返回节点值 |
parentNode | 返回元素的父节点 |
遍历XML 文档的DOM 元素方法
方法名 | 说明 |
---|---|
getElementById(id) | 返回文档中由id指定的元素 |
getElementByTagName(name) | 返回当前元素中指定标记名的子元素的数组 |
hasChildNodes() | 返回一个布尔值,指示元素是否有子元素 |
getAttribute(name) | 返回指定名称的元素的属性值 |
3.3 使用DOM动态编辑页面
属性/方法 | 描述 |
---|---|
document.createElement(tagName) | 文档对象上的createElement方法可以创建由tagName指定的元素。如果以串div作为方法参数,就会生成一个div元素 |
document.createTextNode(text) | 文档对象的createTextNode方法会创建一个包含静态文本的节点 |
<element> .appendChild(childNode) | appendChild方法将指定的节点增加到当前元素的子节点列表(作为一个新的子节点)。例如,可以增加一个option元素,作为select元素的子节点 |
<element> .getAttribute(name) | 获得元素中name属性的值 |
<element> .setAttribute(name, value) | 设置元素中name属性的值 |
<element> .insertBefore(newNode, targetNode) | 这个方法将节点newNode作为当前元素的子节点插到targetNode元素前面 |
<element> .removeAttribute(name) | 这个方法从元素中删除属性name |
<element> .removeChild(childNode) | 这个方法从元素中删除子元素childNode |
<element> .replaceChild(newNode, oldNode) | 这个方法将节点oldNode替换为节点newNode |
<element> .hasChildnodes() | 这个方法返回一个布尔值,指示元素是否有子元素 |
实例:使用DOM和JavaScript创建动态内容
dynamicContent.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动态编辑网页</title>
<script type="text/javascript">
var xmlHttp;
var requestType = "";
function createXMLHttpRequest() {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
function startRequest( requestedList) {
requestType = requestedList;
createXMLHttpRequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET", "library.xml", "true");
xmlHttp.send(null);
}
function handleStateChange() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
clearResults();
parseResults();
}
}
}
function clearResults(){
var header = document.getElementById("header");
if(header.hasChildNodes()){
header.removeChild(header.childNodes[0]);
}
var tableBody = document.getElementById("resultsBody");
while(tableBody.childNodes.length>0){
tableBody.removeChild(tableBody.childNodes[0]);
}
}
function parseResults(){
var results = xmlHttp.responseXML;
var items = null;
var item = null;
var books = null;
var magazines = null;
if(requestType == "books"){
books = results.getElementsByTagName("books");
items = books[0].getElementsByTagName("book");
for(var i = 0;i<items.length;i++){
item = items[i];
name1 = item.getElementsByTagName("name")[0].firstChild.nodeValue;
author = item.getElementsByTagName("author")[0].firstChild.nodeValue;
year = item.getElementsByTagName("year")[0].firstChild.nodeValue;
price = item.getElementsByTagName("price")[0].firstChild.nodeValue;
addTableRow(name1,author,year,price);
}
}else if(requestType == "magazines"){
magazines = results.getElementsByTagName("magazines");
items = magazines[0].getElementsByTagName("magazine");
for(var i = 0;i<items.length;i++){
item = items[i];
name1 = item.getElementsByTagName("name")[0].firstChild.nodeValue;
year = item.getElementsByTagName("year")[0].firstChild.nodeValue;
volume = item.getElementsByTagName("volume")[0].firstChild.nodeValue;
total = item.getElementsByTagName("total")[0].firstChild.nodeValue;
addTableRow(name1,year,volume,total);
}
}
var header = document.createElement("p");
var headerText = document.createTextNode("查询结果如下:");
header.appendChild(headerText);
document.getElementById("header").appendChild(header);
document.getElementById("resultsTable").setAttribute("border","1");
}
function addTableRow(p1,p2,p3,p4) {
var row = document.createElement("tr");
var cell = createCellWithText(p1);
row.appendChild(cell);
cell = createCellWithText(p2);
row.appendChild(cell);
cell = createCellWithText(p3);
row.appendChild(cell);
cell = createCellWithText(p4);
row.appendChild(cell);
document.getElementById("resultsBody").appendChild(row);
}
function createCellWithText(text) {
var cell = document.createElement("td");
var textNode = document.createTextNode(text);
cell.appendChild(textNode);
return cell;
}
</script>
</head>
<body>
<p>查看图书或杂志</p>
<form action="#">
<input type="button" value="查看图书" onclick="startRequest('books');" />
<input type="button" value="查看杂志" onclick="startRequest('magazines');" />
</form>
<span id="header"></span>
<table id="resultsTable" border="0">
<tbody id="resultsBody"></tbody>
</table>
</body>
</html>
library.xml
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<library>
<books>
<book id="101">
<name>Java</name>
<author>张三</author>
<year>2021.12</year>
<price>88.50</price>
</book>
<book id="102">
<name>Oracle</name>
<author>李四</author>
<year>2021.11</year>
<price>33.80</price>
</book>
<book id="103">
<name>MySql</name>
<author>王五</author>
<year>2021.12</year>
<price>33.80</price>
</book>
<book id="104">
<name>HTML</name>
<author>小明</author>
<year>2021.12</year>
<price>33.80</price>
</book>
</books>
<magazines>
<magazine>
<name>计算机网络</name>
<year no="1">2021</year>
<volume>21</volume>
<total>147</total>
</magazine>
<magazine>
<name>操作系统</name>
<year no="1">2021</year>
<volume>22</volume>
<total>148</total>
</magazine>
</magazines>
</library>
四、AJAX的常用应用
4.1 AJAX适用场景
- 表单驱动的交互
- 深层次的树的导航
- 快速的用户与用户间的交流响应
- 类似投票、yes/no等无关痛痒的场景
- 对数据进行过滤和操纵相关数据的场景
- 普通的文本输入提示和自动完成的场景
4.2 AJAX不适用场景
- 部分简单的表单
- 搜索
- 基本的导航
- 替换大量的文本
- 对呈现的操纵
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!