前言
在现代网站和应用程序中,另一个非常常见的任务是从服务器中检索数据项以更新网页的各个部分,而不必加载整个新页面。
这个看似很小的细节对网站的性能和行为产生了巨大影响,因此在本文中,我们将解释这一概念,并研究使之成为可能的技术,例如XMLHttpRequest和Fetch API。
最初,在Web上加载页面很简单-您将向网站发送请求到服务器,只要没有任何问题,就会将构成该页面的资产下载并显示在您的计算机上。
过程:
- 客户端发送请求
- 服务端处理数据
- 服务端发送响应
- 客户端显示数据
这种模型的问题在于,每当您要更新页面的任何部分时,都必须再次加载整个页面。 这是非常浪费的,并且会导致不良的用户体验,尤其是当页面变得越来越大和越来越复杂时。
Ajax技术介绍
可以通过使用XMLHttpRequest之类的API或最近使用的Fetch API来实现从客户端获取数据。 这些技术允许网页直接对服务器上可用的特定资源发送HTTP请求,并在显示结果之前根据需要格式化响应返回的结果数据。
注意:在早期,这种通用技术被称为异步JavaScript和XML(Ajax),因为它倾向于使用XMLHttpRequest来请求XML数据。 如今通常不是这种情况(您更有可能使用XMLHttpRequest或Fetch来请求JSON),但是结果仍然相同,并且术语“ Ajax”仍然经常用于描述该技术。
从服务器获取数据的模型:
Ajax模型的过程:
- 网页向Ajax请求数据
- Ajax向服务器请求数据
- 服务器处理数据并响应给Ajax
- Ajax再响应给页面显示
Ajax模型涉及使用Web API作为代理来更智能地请求数据,而不仅仅是让浏览器重新加载整个页面。 让我们考虑一下它的重要性:
转到您喜欢的信息丰富的网站之一,例如Amazon,YouTube,CNN等,然后加载它。
现在搜索一些东西,例如新产品。 主要内容将更改,但是周围的大多数信息(如页眉,页脚,导航菜单等)将保持不变。
这确实是一件好事,因为:
页面更新要快得多,您不必等待页面刷新,这意味着网站感觉更快,响应速度更快。
每次更新下载的数据更少,这意味着更少的带宽浪费。 在宽带连接的台式机上,这可能不是一个大问题,但在移动设备和没有普遍存在的快速Internet服务的发展中国家中,这是一个主要问题。
为了进一步加快速度,某些站点在首次请求时还将资产和数据存储在用户的计算机上,这意味着在以后的访问中,它们将使用本地版本,而不是每次首次加载页面时都下载新副本。 内容仅在更新后才从服务器重新加载。
客户端使用本地数据过程图解:
Ajax请求案例
让我们看看同时使用XMLHttpRequest和Fetch处理异步请求的方式。我们将从几个不同的文本文件中请求数据,并使用它们填充内容区域。
这一系列文件将充当我们的假数据库; 在实际的应用程序中,我们更有可能使用服务器端语言(如PHP,Python或Node)从数据库请求数据。 但是,在这里,我们希望保持简单,并专注于客户端部分。
XMLHttpRequest
XMLHttpRequest(通常缩写为XHR)现在是一种相当古老的技术
首先,请在计算机上的新目录中制作ajax-start.html和四个文本文件verse1.txt,verse2.txt,verse3.txt和verse4.txt的本地副本,实现异步切换数据的效果
准备html结构和样式:
添加js实现异步获取数据:
在<script>
元素内,添加以下代码。 这会在常量中存储对<select>
和<pre>
元素的引用,并定义一个onchange事件处理函数,以便在更改select的值时,其值作为参数传递给调用的函数updateDisplay()。(pre标签用于显示数据,pre标签可以控制空格和换行,根据select标签的值切换不同的数据)
<!--获取两个有元素节点变量-->
const verseChoose=document.querySelector('select');
const poemDisplay=document.querySelector('pre');
//每次选择一个值的时候都触发该事件
verseChoose.onchange=function()
{
//获取选项值
const verse=verseChoose.value;
//执行异步动作函数,传递选项值
updateDispaly(verse);
}
将参数和请求的文件路径相互关联:
我们将通过构造一个指向要加载的文本文件的相对URL来开始我们的功能,稍后我们将需要它。 任何时候<select>
元素的值都与所选<option>
内部的文本相同(除非您在value属性中指定不同的值),例如“ Verse 1”。 对应的verse文本文件为“ verse1.txt”,并且与HTML文件位于同一目录中,因此仅使用文件名即可。
但是,Web服务器通常区分大小写,并且文件名中没有空格。 要将“ Verse 1”转换为“ verse1.txt”,我们需要将V转换为小写,删除空格,并在末尾添加.txt。 这可以通过replace(),toLowerCase()和简单的字符串连接来完成。 在updateDisplay()函数内添加以下行:
创建请求对象:
要开始创建XHR请求,您需要使用XMLHttpRequest()构造函数创建一个新的请求对象。
You can call this object anything you like, but we’ll call it request to keep things simple
设置请求的方法和url:
接下来,您需要使用open()方法来指定用于从网络请求资源的HTTP请求方法及其URL。 我们将仅在此处使用GET方法并将URL设置为我们的url变量
设置请求响应数据类型:
接下来,我们将期望的响应类型(由请求的responseType属性定义)设置为文本。
This isn’t strictly necessary here — XHR returns text by default — but it is a good idea to get into the habit of setting this in case you want to fetch other types of data in the future.
触发响应后执行客户端的动作:
从网络获取资源是异步操作,这意味着您必须等待该操作完成(例如,资源从网络返回),然后才能对该响应执行任何操作,否则,将引发错误。
通俗的讲就是客户端请求资源,客户端继续执行客户端的任务,然后监听服务端的消息,当客户端收到服务端发送回来的数据,就能够对响应数据执行操作。
发送请求:
以上的所有操作都是对请求对象进行设置,该请求还没有发送,我们调用请求的send方法,才会真正的发送请求
显示默认数据:
目前的示例存在一个问题,即该示例在首次加载时不会显示任何诗歌。要解决此问题,请在代码底部(恰好在</ script>
标记上方)添加以下两行以默认加载第1节 verse 1,并确保<select>
元素始终显示正确的值:
全部JSCode:
<script>
<!--获取两个有元素节点变量-->
const verseChoose = document.querySelector('select');
const poemDisplay = document.querySelector('pre');
//设置默认选项值
verseChoose.value = 'Verse 1';
//设置默认请求的异步数据
updateDisplay('Verse 1');
//每次选择一个值的时候都触发该事件
verseChoose.onchange = function () {
//获取选项值
const verse = verseChoose.value;
//执行异步动作函数,传递选项值
updateDisplay(verse);
}
function updateDisplay(verse) {
/*
选项的值分别是Verse 1;Verse 2;Verse 3;Verse 4;所有传递的参数都有大写字符和空格,因为要将参数作为url的一部分传递到服务器,所以我们需要将参数字符去掉空格,以及全部转换为小写。
将参数的值拼接为url的一部分
*/
//去掉空格
verse = verse.replace(" ", "");
//将字符串的值转化成小写
verse = verse.toLowerCase();
//拼接字符串
let url = verse + ".txt";
// 构建请求对象
let request = new XMLHttpRequest();
// 设置资源请求方法以及请求的url
request.open('GET', url);
//设置请求的响应类型
request.responseType = 'text';
//加载请求对象时运行函数
request.onload = function () {
//设置将位置区域填上从服务端响应的数据
poemDisplay.textContent = request.response;
}
//发送请求
request.send();
}
</script>
效果:
使用Fetch代码实现Ajax(暂时略)
首先,我们调用fetch()方法,并将要获取的资源的URL传递给该方法。 这是XHR中的request.open()的现代等效项,另外,您不需要任何与.send()等效的项。(fetch方法更加方便)