hello,Ajax(零基础入门篇)

1,976 阅读17分钟

前言

这是一篇ajax的基础文章,在半年前我第一次听说ajax,于是去网上查阅了一些资料看看究竟是何方圣神,发现根本看不懂。我太弱了。

前几天才对ajax了解了一些皮毛。所以我想写一篇0基础刚开始学技术就能看懂的ajax文章。 希望能够帮助到还没接触到ajax的小可爱。通过这篇文章你将了解:

  • ajax是什么
  • ajax的作用
  • ajax的原理
  • 如何实现ajax

ajax简介

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

Ajax:标准读音 [ˈeɪˌdʒæks] ,中文音译:阿贾克斯,它是浏览器提供的一套方法,可以让用户在不刷新页面的情况下更新用户数据,提高用户体验。也就是在用户浏览网页的同时局部跟新页面的数据。

这里列举两个生活中的例子,让大家有跟深刻的体会。

situation1:比如浏览网页的时候浏览到底部有一个‘加载更多’按钮,之后跟多的数据就会在页面中渲染出来,在呈现数据的过程中页面是没有刷新的只是在原有数据的后面加上了数据,在不刷新页面的情况下向服务器发送请求,然后服务器向客户端返回数据。

situation2: 另外一个场景大家更熟悉了,比如某些手游新人注册的时候,当你输入一个用户名的时候会立马弹出该用户名已注册,然后不得不更换一个用户名直到用户名没有被其他人注册过。 如果用户名没有被注册就提示可用。大家应该能想到注册页面是表单form。这样的好处是避免用户填完所有的注册信息发送到浏览器后再返回错误,避免页面跳转,避免用户重新填写表单的情况。

主要作用就是在不刷新页面的情况下向服务器端发请求与服务器端进行交互从而更改客户端页面的数据或状态,主要目的就是为了提高用户体验。

ajax原理

传统的网站中浏览器和服务器之间进行通信的时候浏览器无法继续进行其他操作,比如向下拉动页面。用户体验很不好,所以请求的发送和响应的接收不能由浏览器自己去完成,如果找一个代理人帮忙做,那样浏览器就可以响应用户其他的操作,岂不美哉?

实际上ajax引擎就是这个中间人,ajax帮浏览器去发送请求,ajax接收服务器端的响应。当ajax接收到服务器端的数据后我们再使用dom方法将内容添加到页面当中。这样就可无刷新更新数据以及用户可进行其他操作。

我们看下面这幅图:领导让秘书帮助自己叫小李,然后自己做别的事情。秘书找啊找找到小李后,小李向领导汇报工作是生活中的常见场景。

Ajax请求数据流程与“领导想找小李汇报一下工作”类似。其中最核心的依赖是浏览器提供的XMLHttpRequest对象,它扮演的角色相当于秘书,使得浏览器可以发出HTTP请求与接收HTTP响应。浏览器接着做其他事情,等收到XHR返回来的数据再渲染页面。
另外在传统的网站中请求和响应过程开发人员是不可控的,ajax引擎与服务器的交互开发人员是可控的。

如果看到这里看不下去了记住ajax他不是一门编程语言,而是一种使用现有标准的新方法。 AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

接下来用代码看看如何实现ajax这个中间件,这里涉及到nodeJs和网络部分的相关知识,如果这两方面不了解后面代码可能会有些看不懂,不过没关系,我尽量把代码解释清楚让大家能够知道相关的一些原理和过程。

ajax实现

1.ajax实现步骤

ajax实现有四步

  • 创建一个ajax对象 ,使用XMLHttpRequest这个函数创建一个实例对象。
  • 告诉ajax对象要发送的请求地址以及请求方式 ,调用xhr下面的open方法
  • 发送请求,使用send方法。
  • 获取服务器响将要响应到客户端的数据,使用xhr下的resopnsText属性就是服务器响应给客户端的数据。

我们看看下面的代码,在终端中用noedmon命令执行app.js启动服务器。(如果这句话看不懂就把app当做前面举例的的第四步中的浏览器,app.js中的功能就是浏览器返回数据给xhr)

app.js
app.get('/first', (req, res) => {
	res.send('Hello, Ajax');
});
html文件:
     <script type="text/javascript">
		// 1.创建ajax对象
		var xhr = new XMLHttpRequest();
		// 2.告诉Ajax对象要向哪发送请求,以什么方式发送请求
		// 1)请求方式 2)请求地址
		xhr.open('get', 'http://localhost:3000/first');
		// 3.发送请求
		xhr.send();
		// 4.获取服务器端响应到客户端的数据
		xhr.onload = function (){
			console.log(xhr.responseText)
		}
	</script>

关于第四步的一个说明: 给xhr绑定onload事件,当请求发送成功onload事件就会自动触发。

代码分析

首先执行html文件,执行html文件后客户端才会向服务端发送请求,服务器才会响应这个ajax,如果浏览器中看到ajax发送过来的字符串就说明请求是成功的。

我们看下面的结果在网页中看到ajax发送过来的字符串说明请求响应成功。

2.服务端向ajax对象返回的数据格式

我们已经知道了ajax实现的四个步骤,其中服务器会向xhr返回数据,数据是以什么格式返回的呢?

ajax中的x指的虽然是xml,在真实的项目中,服务器端大多数情况下会以 JSON 对象作为响应数据的格式。当客户端拿到响应数据时,要将 JSON 数据和 HTML 字符串进行拼接,然后将拼接的结果展示在页面中。

在 http 请求与响应的过程中,无论是请求参数还是响应内容,如果是对象类型,最终都会被转换为对象字符串进行传输。

因此我们要利用JSON.parse()方法将字符串转换成json数据格式。

下面通过代码让服务器返回一个对象,看看不对数据进行处理返回的结果是一个对象还是一个字符串。

app.js:
app.get('/responseData', (req, res) => {
	res.send({"name": "zs"});
});

html:
<script type="text/javascript">
		// 1.创建ajax对象
		var xhr = new XMLHttpRequest();
		// 2.告诉Ajax对象要向哪发送请求,以什么方式发送请求
		// 1)请求方式 2)请求地址
		xhr.open('get', 'http://localhost:3000/responseData');
		// 3.发送请求
		xhr.send();
		// 4.获取服务器端响应到客户端的数据
		xhr.onload = function (){
			 console.log(typeof xhr.responseText)
			// 将JSON字符串转换为JSON对象
			var responseText = JSON.parse(xhr.responseText);
			// 测试:在控制台输出处理结果
			console.log(responseText)
			// 将数据和html字符串进行拼接
			var str = '<h2>'+ responseText.name +'</h2>';
			// 将拼接的结果追加到页面中
			document.body.innerHTML = str;
		}
	</script>

代码分析:

app.js的功能就是服务器向xhr返回{"name": "zs"}这个数据,本应该是json数据但传输的时候以字符串传输。

代码中ajax实现步骤还是前面提到的四步。主要讲一讲onload方法。

先判断响应给客户端数据类型,下图结果控制台输出的第一个值string,就说明对象格式转成了字符。

然后我们将字符串转换为json数据格式后,控制台输出结果看到转换成了json对象。

再利用h2标签将字符串进行拼接并使用document下的方法将结果展示到页面中,也就是结果图右上角二级标题zs。

小小总结一下:在 http 请求与响应的过程中,无论是请求参数还是响应内容,如果是对象类型,最终都会被转换为对象字符串进行传输。我们可以用json相关方法对字符串进行转换json对象,便于获取内容,便于浏览器渲染页面。

ajax向服务器发送请求时参数的传递

向服务请发送请求就会携带请求参数,在传统的网站中请求参数的传递都是根据表单来传递的,表单提交后表单内容就作为请求参数向服务器发送请求,不同的请求方式请求参数会填写到不同的位置,比如get方式会添加到地址栏中,post方式添加到请求体中。

ajax中需要自己拼接请求参数,根据请求方式的不同将请求放到不同的位置上。参数名称与传统网站相比不变,‘username=111&age=19’(参数名=参数值,多个参数值用&进行分割)。下面将以此介绍get和post两种请求方式中请求参数是如何传递的。

1.get方法发送请求

get方法发送的请求参数我们手动拼接好后添加到open方法中的请求地址这个参数中。

我们在服务器端写好一个get请求参数的路由,在地址栏输入该服务器路由地址,看看会有什么结果吧。代码如下:

app.js:
app.get('/get', req, res) => {
	res.send(req.query);
});
html:
<script type="text/javascript">
		// 获取按钮元素
		var btn = document.getElementById('btn');
		// 获取姓名文本框
		var username = document.getElementById('username');
		// 获取年龄文本框
		var age = document.getElementById('age');
		// 为按钮添加点击事件
		btn.onclick = function () {
			// 创建ajax对象
			var xhr = new XMLHttpRequest();
			// 获取用户在文本框中输入的值
			var nameValue = username.value;
			var ageValue = age.value;
			// 拼接请求参数
			var params = 'username='+ nameValue +'&age=' + ageValue;
			// 配置ajax对象
			xhr.open('get', 'http://localhost:3000/get?'+params);
			// 发送请求
			xhr.send();
			// 获取服务器端响应的数据
			xhr.onload = function () {
				console.log(xhr.responseText)
			}
		}
	</script>

代码分析

app.js文件中路由中返回的结果就是请求参数, html中监听按钮是否被点击,点击后就创建了ajax对象,html中的xhr.open方法中对请求参数进行了拼接。如果创建成功浏览器就会得到服务端响应的结果。

执行html文件。我们看看输出结果是什么:

在页面中输入姓名111和年龄19.打开开发者工具查看xhr请求,我们看到请求参数没有问题。拼接成功,见下图红色部分中问号后面部分就是拼接的请求参数。

请求发送成功怎么判断服务器有没有接收到做出响应呢,在html页面我们用 console.log(xhr.responseText)答应响应的结果,所以判断控制台是否输出响应的结果就可以了。页面中控制台打印的结果如下,说明服务器接收到了get请求。

2.post方法发送请求

post方法发送请求请求参数是要设置在请求体中的,与get方法不同,拼接好的请求参数要放到send方法中。同时post请求要在请求报文中明确设置请求参数内容的类型,也就是content-type属性。

在ajax对象下有一个setRequestHeader方法用来设置请求报文中的请求头信息。 下面通过代码来进行演示。创建post方式的请求路由,执行对应的html文件在地址栏中输入对应的路由地址。看看发生了什么。

app.js:
app.post('/post', (req, res) => {
	res.send(req.body);
});
html:
<script type="text/javascript">
		// 获取按钮元素
		var btn = document.getElementById('btn');
		// 获取姓名文本框
		var username = document.getElementById('username');
		// 获取年龄文本框
		var age = document.getElementById('age');
		// 为按钮添加点击事件
		btn.onclick = function () {
			// 创建ajax对象
			var xhr = new XMLHttpRequest();
			// 获取用户在文本框中输入的值
			var nameValue = username.value;
			var ageValue = age.value;
			// 拼接请求参数
			var params = 'username='+ nameValue +'&age=' + ageValue;
			// 配置ajax对象
			xhr.open('post', 'http://localhost:3000/post');
			// 设置请求参数格式的类型(post请求必须要设置)
			xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			// 发送请求
			xhr.send(params);
			// 获取服务器端响应的数据
			xhr.onload = function () {
				console.log(xhr.responseText)
			}
		}
	</script>

代码分析

点击btn按钮后创建了ajax对象,对ajax对象进行配置,用setRequestHeader对post请求参数的格式进行规定,将post请求发送过去,然后获取服务端响应的数据将数据打印到控制台中。执行html文件,我们将表单中填上数据点击提交后可以看到控制台中输出了我们在表单中输出的数据,也就是服务器的接收到请求并作出了响应。post方法发送请求成功。

我们看看network中的Form Data,Form Data直译即表单数据。我们也看到了表单的数据,也就是成功拼接到请求参数。
小小总结一下post方式向服务器发送请求的两个要点。

  • 请求参数要放到xhr对象的send方法中发送
  • 要利用xhr下的setRequestHeader方法添加http报文头规定请求参数的格式。

3.请求参数的格式

客户端向服务器端传递请求参数的格式有两种。一种是很熟悉的属性名:属性值&属性名:属性值。另外一种就是json数据格式。

不同的请求参数格式在setRequestHeader中的Content-type属性值不一样。

1. application/x-www-form-urlencoded

格式形式:name=zhangsan&age=20&sex=男
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

2. application/json

 格式形式:{name: 'zhangsan', age: '20', sex: '男'}
 xhr.setRequestHeader('Content-Type', 'application/json');

来看一个传递json字符串的例子吧

app.post('/json', (req, res) => {
	res.send(req.body);
});
html:
<script type="text/javascript">
		// 1.创建ajax对象
		var xhr = new XMLHttpRequest();
		// 2.告诉Ajax对象要向哪发送请求,以什么方式发送请求
		// 1)请求方式 2)请求地址
		xhr.open('post', 'http://localhost:3000/json');
		// 通过请求头告诉服务器端客户端向服务器端传递的请求参数的格式是什么
		xhr.setRequestHeader('Content-Type', 'application/json');
		// JSON.stringify() 将json对象转换为json字符串
		// 3.发送请求
		xhr.send(JSON.stringify({name: 'lisi', age:50}));
		// 4.获取服务器端响应到客户端的数据
		xhr.onload = function (){
			console.log(xhr.responseText)
		}
	</script>

代码解析: 与常规格式不同的是setRequestHeader的参数改变为'application/json',然后将json对象转换为字符串进行传递,同样也是把请求参数放到send函数中。因为json格式只存在post请求参数中。最后获取到响应将结果打印到控制体。如下图所示:

为什么要设置期该区参数格式,因为要告诉服务器当前传递的请求参数格式呢,因为客户端传递不同类型的请求参数服务端接收的格式是不一样的。传递参数的时候必须要以字符串进行传输,所以将json对象转换成字符串类型。

ajax获取服务端的响应

ajax获取服务端的响应其实前面已经出现过了,就是xhr对象下的onload方法。这里将另外一种出现不多的方法。

1.什么是ajax状态码

ajax状态码与http状态码(不知道http状态码可以自己查)不同。ajax状态码是创建一个ajax对象,配置ajax对象,发送请求,以及接收完服务端响应数据的过程中对应的一个数值。这个数值就是ajax状态码。通过状态码我们知道当前请求进行到了哪一步。

ajax状态码主要有以下五种:

  • 0:未初始化 -- 尚未调用.open()方法;
  • 1:启动 -- 已经调用.open()方法,但尚未调用.send()方法;
  • 2:发送 -- 已经调用.send()方法,但尚未接收到响应;
  • 3:接收 -- 已经接收到部分响应数据;
  • 4:完成 -- 已经接收到全部响应数据,而且已经可以在客户端使用了

在xhr下有一个readyState存贮了ajax状态码。我们可以通过判断ajax状态码状态让客户端做出响应。

2. onreadystatechange方法的出现

下面通过代码展示另外一种通过onreadystatechange获取服务器端响应的操作。

<script type="text/javascript">
		var xhr = new XMLHttpRequest();
		// 0 已经创建了ajax对象 但是还没有对ajax对象进行配置
		console.log(xhr.readyState);
		xhr.open('get', 'http://localhost:3000/readystate');
		// 1 已经对ajax对象进行配置 但是还没有发送请求
		console.log(xhr.readyState);
		 xhr.send();
		// 当ajax状态码发生变化的时候出发
		xhr.onreadystatechange = function() {
			// 2 请求已经发送了
			// 3 已经接收到服务器端的部分数据了
			// 4 服务器端的响应数据已经接收完成
			console.log(xhr.readyState);
			// 对ajax状态码进行判断 如果状态码的值为4就代表数据已经接收完成了
			if (xhr.readyState == 4) {
				console.log(xhr.responseText);
			}
		} 

		<!--xhr.send();-->
		
	</script>

代码说明:上面的注释很清楚了,如果有问题可以评论区骚扰我哈。

onreadystatechange方法是在状态码发生变化的时候触发的,如果我们把send方法写在最后就会报错。

报错原因

因为onreadystatechange方法是状态码发生变化的时候该方法才能够被触发,如果放在send方法放在前面就没有什么作用了,因为send方法虽然会引起状态码的变化,但是onreadystatechange方法在执行上下文中只是一个没有被赋值变量,无法执行。

就好像你要用手机听歌但是手机没有电无法听歌一样。这里就好比send触发的时候状态码在变化但是你没有自动打印状态码的函数一样。

改进方法:所以我们把send方法放在后面,这个时候执行栈中就有了onreadystatechange这个函数。就不会报错。

我们对上面的代码进行修改,这里直接上结果。没有报错,并且状态为4的时候输出了服务器响应的结果。完美。

3. onreadystatechange事件 VS onload事件

目前我们知道了两种方法,一种是通过判断状态码是否发生变化就触发的 onreadystatechange函数,另外一种是前面提到的浏览器接收完响应就会触发的onload方法,这两总方法有什么差异呢?我来给您画个表吧

区别 onload事件 onreadystatechange
是否兼容ie低版本 不兼容 兼容
是否要判断ajax状态 不需要 需要
被调用次数 一次 多次

通过表格我们知道onload相对于更为简单效率高,但是在ie低版本浏览器可以使用onreadystatechange。

参考链接

文章末尾

文章写完了,回顾一下,最开始介绍ajax是什么,他是编程语言吗?他的主要作用是什么?原理是什么?然后如何使用ajax,通过一些代码介绍了ajax和服务器进行交互,然后浏览器又是如何拿到结果渲染页面的。其实整片文章就是讲开篇的第二章张图,在此基础上进行了扩充。

再看看这幅图吧,希望能给你带来更深的启发和思考。欢迎大家的评论区留言谈谈感悟。

如果有看不明白的地方就麻烦在评论区告诉我呗,有理解不到位的地方十分欢迎指正。


这篇文章是一个简单的入门,后续深入学习还是必不可少滴。

如果喜欢觉得有用,记得留下美丽的痕(dian)迹(zan)哦。