ajax详解

一.前置知识

postman

1.上网的本质

通过网络给服务器要数据或把数据扔给服务器。

2.什么是URL

URL(全称是UniformResourceLocator)中文叫统一资源定位符,用于标识互联网上每个资源的唯一存放位置。浏览器只有通过URL地址,才能正确定位资源的存放位置,从而成功访问到对应的资源。

常见的URL举例:

  • http://www.baidu.com

  • http://www.taobao.com

3.客户端服务器通信过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ckDV4TsD-1597495967134)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg)]

4.什么是API接口

使用 Ajax 请求数据时,被请求的 URL 地址,就叫做数据接口(简称接口)。同时,每个接口必须有请求方式。

**接口测试工具:**postman等。

接口文档:

接口文档,顾名思义就是接口的说明文档,它是我们调用接口的依据。好的接口文档包含了对接口URL,参数以及输出内容的说明,我们参照接口文档就能方便的知道接口的作用,以及接口如何进行调用。

接口文档包含的几个部分:

接口文档可以包含很多信息,也可以按需进行精简,不过,一个合格的接口文档,应该包含以下6项内容,从而为接口的调用提供依据:

接口名称: 用来标识各个接口的简单说明,如登录接口,获取图书列表接口等。

接口URL: 接口的调用地址。

调用方式: 接口的调用方式,如 GET 或 POST。

参数格式: 接口需要传递的参数,每个参数必须包含参数名称、参数类型、是否必选、参数说明这4项内容。

响应格式: 接口的返回值的详细描述,一般包含数据名称、数据类型、说明3项内容。

返回示例(可选): 通过对象的形式,例举服务器返回数据的结构。

二.认识Ajax(了解)

1.什么是Ajax

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UsMhpawX-1597495967139)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image004.png)]

中文的说法:阿贾克斯

Ajax:Asynchronous javascript and xml,异步的javascript和xml。

是指一种创建交互式网页应用的网页开发技术。

Ajax只是一门综合性的技术,本身是老技术,新应用。

这些技术就包括了:

  • 服务端:服务端的语言(php、node),数据库(mysql、mongodb)

  • 浏览器端:HTML、CSS、JavaScript、DOM

  • 连接:HTTP、XMLHttpRquest对象

要全面掌握ajax,必须有熟悉前端和后端的知识。

请问:ajax到底是前端程序员的活还是后端程序的活?

2.为什么需要Ajax

可以站在两个角度来看待这个问题

  • 提升用户体验 ---- 早期

  • 前后端分离开发模式 — 现在

(1).提升用户体验

在软件开发领域中,只有两种架构:

  • C/S,client/server,在用户的电脑必须要安装特定的客户端软件,比如qq

  • B/S,browser/server,用浏览器就可以使用服务。

B/SC/S备注
可维护性/更新非常方便比较麻烦,每个用户都需要更新客户端软件既包括软件提供方,也包括用户
性能胖服务端/瘦客户端,性能较差胖客户端/瘦服务端 将一部分的功能放到用户的客户端上,性能更好针对软件提供方
用户体验针对用户

其实,可维护性和性能,都会对用户体验有影响。

B/S和C/S,相比较而言,用户体验是很差的,最重要的体现就是在响应的速度方面。

所以,既有具备B/S的优势,同时又希望能够具备C/S模式的的快速响应体验。

由于http的请求/响应模型,和服务端挂钩的任何一次用户的操作,都是一个全新的请求,会导致整个页面刷新了,从而大大降低了响应速度。

比如注册表单:

Ajax的出现,就可以让B/S架构能够具备C/S架构的快速响应能力。它是通过局部刷新(异步刷新)来实现的。

(2).前后端分离开发模式

传统的开发模式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mw0rYZNs-1597495967142)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg)]

前后端分离的开发模式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x0uxtOmS-1597495967146)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg)]

在新的开发模式下,前端向后端要数据,就只能使用ajax的方式。

在今天的前端开发中,ajax的作用:

  • 提升用户体验

  • 实现前后端分离开发

3.Ajax的发展历程

2005年2月,Adaptive Path公司的Jesse James Garrett最早提出这个概念。它出现在Garrett的文章“Ajax: A New Approach to Web Applications”中。这篇文章描述了混合使用XHTML、CSS、JavaScript、DOM、XMLHttpRequest进行Web开发将会成为一种新的趋势。

同年,Google在三大产品中使用了Ajax技术:

  • Google Suggest

  • Google Maps

  • Gmail

ajax变迁史

  • 传统的Ajax — XMLHttpRequest

  • 新的ajax方式 — fetch/axios

  • 反向Ajax

三.传统的Ajax(了解)

1.核心—XMLHttpRequest对象

XMLHttpRequest是一套可以在Javascript语言中通过http协议传送或接收XML及其他数据的一套API。

XMLHttpRequest,简称为XHR对象,本质上就是一个对象。

可以从两个方面来看:

  • XHR对象所处的位置

  • XHR对象有哪些属性和方法

(1).XHR对象所处的位置

Ajax是一系列技术的综合运用。它包括浏览器端和服务端的。

XHR本身是在浏览器端的,是js中对象。

XHR对象,可以向服务端发送http请求,并且处理服务端返回的响应。

XHR相当于是一个通道,利用这个通道,浏览器和服务端可以悄悄的通信。

(2).XHR对象有哪些属性和方法

重要属性有:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g3Vao4a4-1597495967152)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg)]

重要方法有:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hGePk2gp-1597495967154)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg)]

XMLHttpRequest 对象用于在后台与服务器交换数据。(这个后台是指悄悄的)

XMLHttpRequest 对象是开发者的梦想,因为您能够:

  • 在不重新加载页面的情况下更新网页 (股票信息)

  • 在页面已加载后从服务器请求数据 (异步,懒加载)

  • 在页面已加载后从服务器接收数据

  • 在后台向服务器发送数据

2.快速入门案例

目标:检测用户名是否可用(类似于京东的用户注册)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vFgfcVEP-1597495967156)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image014.jpg)]

需要实现两个版本:

  • 传统的检测方式

  • 利用ajax的检测方式

(1).传统方式检测用户名

第一步,准备一个注册的表单页面

如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4YOc6u7N-1597495967158)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image016.jpg)]

第二步,安装express和ejs

安装如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-95ddK81W-1597495967161)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image018.jpg)]

第三步,编写代码载入注册页面

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X1Ht0Hqv-1597495967162)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image020.jpg)]

启动,访问如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3SwZUG2r-1597495967167)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image022.jpg)]

第四步,当用户提交表单时,检测用户名是否可用

注意,action为空或#,就表示提交给当前路径。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwsVd1sR-1597495967168)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image024.jpg)]

先安装body-parser中间件,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N8kBSN87-1597495967170)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image025.png)]

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FwfOMjKA-1597495967172)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image027.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s7Vu7Tyo-1597495967175)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image028.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QNzOb58Y-1597495967177)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image030.jpg)]

从功能的角度来讲,这个是可以的。

但是从用户体验来将,这个是非常糟糕的。

在这个检测中,当点击提交之后,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i28eoevT-1597495967180)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image032.jpg)]

页面发生了跳转,是一个全新的请求。

如果用户名已经被占用,就需要退回到注册页面,又是一个页面刷新,有很多信息已经重置了,再次填写一遍,所以这个体验是非常糟糕的。

(2).利用ajax方式检测用户名

A.分析过程

在传统的检测方式中,是将所有的信息填写完毕,然后点击提交才开始检测的。

用户希望的方式是一旦用户名填写完毕,就立即检测告诉我结果。

这就需要我们在用户名填写完毕的时候,向服务端发一个http请求,然后返回是否可用的结果。

所以,需要有两个点:

  • 什么时机发http请求

  • 如何发http请求并接受返回结果

什么时机发http请求

在市区焦点的时候,发请求,就是blur事件。

如何发http请求并接受返回结果

此时,就需要使用ajax,应该使用xhr对象来实现。

Ajax的实现过程:

  • 创建xhr对象

  • 建立和服务端的连接

  • 监听服务端的状态变化

  • 发送请求

B.具体实现

第一步,准备表单页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YMdaPN0s-1597495967183)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image034.jpg)]

第二步,提供server,载入静态页面

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EndAZ7Mv-1597495967184)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image036.jpg)]

启动服务,访问如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AMzJTAP9-1597495967189)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image040.jpg)]

第三步,需要注册blur事件,发起ajax请求

在reg2.ejs中,来编写代码,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P9ekyuFA-1597495967191)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image042.jpg)]

可以先测试一下:

在这里插入图片描述

说明,http请求已经发送了。

第四步,在服务端处理/check请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wNBVNtiu-1597495967193)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image044.jpg)]

重启,测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qyeVpwO0-1597495967195)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image046.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JrHVvBQu-1597495967198)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image048.jpg)]

(3).小结

  • 有了ajax之后,用户体验大大提升。

  • 在使用ajax之后,http请求/响应是有的,但是整个页面并没有刷新,这就是异步刷新(局部刷新)技术。

  • Ajax的核心,是XHR对象,所有的过程都是由XHR对象来实现的。XHR对象是重点

  • 在进行ajax请求的时候,一定要结合network面板分析http请求

  • Network面板中,有一项XHR,就是专门针对ajax请求的

3.创建XHR对象

在标准的浏览器中,使用XMLHttpRequest构造器来new 即可。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HuwbVRE3-1597495967199)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image050.jpg)]

输出如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vfd6I5fg-1597495967201)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image052.jpg)]

需要注意的是:在ie6/ie7浏览器,是不支持这种写法的。(了解即可)

需要使用activeXObject对象来创建。

比如:

var xhr = new ActiveXObject(“Microsoft.XMLHTTP”); //最原始方式 ie5/ie6

var xhr = new ActiveXObject(“Msxml2.XMLHTTP”); //升级 ie7及以上

不需要自己来写代码创建,原因有二:

  • ie6/7已经很老了,可以不予支持

  • 如果需要支持ie6/ie7,请使用jQuery

4.请求方式

一旦创建好了xhr对象,就需要建立和服务端的连接。

需要使用open方法,格式如下:

xhr.open(请求方式,url,async)

其中,请求方式,有get和post两种。

Get和post都是在浏览器端向服务端发http请求的。

在发送http请求的时候,可以携带数据,针对数据的大小、形式、安全度是有所不同的:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OearihBW-1597495967203)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image054.png)]
在这里插入图片描述

(1).get

格式为:xhr.open(‘get’,url)

其中,

这个get是字符串,大小写都可以的。

url表示请求的地址,通常是带有查询字符串的。

如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qNPiIlLH-1597495967205)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image056.jpg)]

针对get请求,需要发送,使用xhr.send来实现的。

send是用来发送请求正文的。只有调用send方法,才说明请求发送完毕的。

由于,get请求的请求正文是空的,所以可以不写任何内容,但一般使用null来表示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tPDHkCuG-1597495967206)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image058.jpg)]

针对get请求,需要注意一些特殊符号:

  • 对中文 (ie浏览器会有乱码)

  • =

  • &

= 和 & 本身是查询字符串中的符号,会有问题。

如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JeEn1ZcF-1597495967208)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image060.jpg)]

Ie的中文问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t2qOklKJ-1597495967211)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image062.jpg)]

所以,千万不要相信用户的输入,凡是用户输入的内容,都需要进行处理。

此处,必须要进行编码 ---- encodeURIComponent

使用如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aGNLHcPV-1597495967214)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image064.jpg)]

再次访问:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B6oz79QC-1597495967216)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image066.jpg)]

编码的结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SvIk8HDM-1597495967217)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image068.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wRhkH3xs-1597495967219)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image070.jpg)]

针对编码,我们无需解码,浏览器会自动解码。

(2).post

针对post请求,有如下几个地方:

  • xhr.open(“post”,url)

  • 需要使用setRequestHeader()把传递的数据组织为xml格式

  • 调用send()方法时,需要传递数据,作为请求正文

  • 特殊的符号(=和&)、中文需要编码

  • Post请求的同时也可以使用查询字符串来传递数据

使用如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AJHxxHU9-1597495967221)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image072.jpg)]

对应的,在服务端,需要使用post方式来处理请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SSWmjFe0-1597495967223)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image074.jpg)]

重启,测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gg5e5a0C-1597495967224)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image076.jpg)]

在开发过程中,get方式更为常见(占90%),post用的比较少。

get,主要是用于从服务端获取数据的。

post,主要是用于向服务端添加数据的。

5.什么是URL编码

URL 地址中,只允许出现英文相关的字母、标点符号、数字,因此,在 URL 地址中不允许出现中文字符。

如果 URL 中需要包含中文这样的字符,则必须对中文字符进行编码(转义)。

**URL编码的原则:**使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。

URL编码原则的通俗理解:使用英文字符去表示非英文字符。

如何对URL进行编码与解码?

浏览器提供了 URL 编码与解码的 API,分别是:

  • encodeURI() 编码的函数

  • decodeURI() 解码的函数

由于浏览器会自动对 URL 地址进行编码操作,因此,大多数情况下,程序员不需要关心 URL 地址的编码与解码操作。

参考:https://blog.csdn.net/Lxd_0111/article/details/78028889

6.序列化和反序列化

  • 把数据对象转换为字符串的过程,叫做序列化,例如:调用 JSON.stringify() 函数的操作,叫做 JSON 序列化。

  • 把字符串转换为数据对象的过程,叫做反序列化,例如:调用 JSON.parse() 函数的操作,叫做 JSON 反序列化。

7.FormData对象

Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tRDMAN28-1597495967226)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image078.jpg)]

FormData对象也可以用来获取网页表单的值:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f1xSk9Xg-1597495967227)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image080.jpg)]

8.同步和异步

(1).同步和异步是什么意思?

同步和异步主要是指代码的执行顺序问题。

同步,按照代码书写的顺序依次执行,代码的执行顺序和代码书写的顺序是一致的。

异步,代码执行的顺序和代码书写的顺序是不一致的。

由于js是单线程的,一次只能处理一个任务。如果某个任务,耗时比较长,后续的任务就需要等待。

为了解决同步的任务等待,所以提出了异步的解决方案。

所谓异步,将某些耗时较长的任务使用异步的方式来处理。这样一来,就将所有的同步任务先执行完毕,然后再执行异步任务,从而提高整体的效率。

在ajax中,如果是同步的请求,那么在结果没有返回之前,你就处于等待状态,不能进行其他操作。

如果是异步的请求,那么在结果返回之前,还可以进行其他的操作。无需等待。

(2).具体实现

通过open方法的第三个参数设置异步或同步,默认true,表示异步。

如果设置为false,就表示同步。

在使用异步的时候,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mqrPqeeZ-1597495967229)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image081.png)]

如果是同步,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aJVnD9WP-1597495967231)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image083.jpg)]

在实际使用时,异步肯定使用较多。

什么情况下需要使用同步?

如果后续的请求,需要使用ajax请求的结果,可以使用同步。

在浏览器端的js中,异步有如下三个地方:

  • setTimeout和setInterval

  • dom中的事件

  • Ajax

如果是服务端的js,异步有:

  • 文件操作

9.状态说明

在ajax的使用过程中,有如下一段代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NMfLCCt9-1597495967233)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image085.jpg)]

涉及到了四个属性:

  • onreadystatechange

  • readyState

  • status

  • responseText

其中,onreadystatechange、readyState和status是和状态有关。

而responseText则是指返回的数据。

Xhr对象,本身有一个属性—readyState,用来描述xhr的状态的。

ReadyState有如下5个值,分别表示不同的阶段:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H3H2rZU7-1597495967234)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image087.png)]

加入调试代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-woG3sCYW-1597495967236)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image089.jpg)]

查看结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6H8cG23M-1597495967237)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image091.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-irjOYrxt-1597495967239)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image093.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2RaXmGfE-1597495967241)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image095.jpg)]

1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VsfaIsYn-1597495967245)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image099.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L0CLM651-1597495967247)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image101.jpg)]

在0~4这5个状态中,其中:

0表示xhr对象已经创建好了

1则表示已经向服务端发送请求了。

这两个值,咱们不需要。

请求一旦发出去,我们比较关心的是服务端的返回情况。服务端到底有没有把数据返回并解析完成。

服务端返回数据并解析的过程,不是一下子就完成,分成了3个阶段,分别对应于3个状态,只有当状态值变为4的时候,才表示解析ok。

请求,我们如何来捕捉这个状态的变化。

此时,就应该使用事件机制,在xhr对象中,就提供了一个事件–readystatechange,用于监听readyState的变化,换言之,请求发送之后,只要readyState发生变化(不包括0和1),就会触发readystatechange事件。

readyStatechange事件是作为onreadystatchchange属性来注册的。

所以,我们需要注册readystatechange事件,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FhkzdIR8-1597495967249)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image103.jpg)]

这个事件处理函数,至少会执行3次(状态有可能会执行多次)。

而我们需要在readyState = 4的状态才能获取数据。

所以,就需要增加一个判断,xhr.readyState == 4

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-orF4AsLP-1597495967250)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image105.jpg)]

除readyState之外,xhr还提供了一个属性 — status,用于获取http响应的状态码。

典型的状态码有如下几个:

  • 200,ok

  • 302,founded

  • 304,not modified

  • 403,forbidden

  • 404,not found

  • 500,服务器内部错误

所以,需要增加一个判断,xhr.status == 200,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GwVAWZPV-1597495967252)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image107.jpg)]

注意:onreadystatechange是全小写,而readyState则是小驼峰命名法则

10.返回数据的方式

在xhr中,针对返回数据的格式,它提供了两个属性:

  • responseXML

  • responseText

(1).responseXML

这个是指数据以XML的格式从服务端返回到浏览器端。

实际上,早期都是使用XML格式的。

在今天,XML这种格式以及非常落后的,在ajax中,几乎不再使用XML这种格式。

因为,XML数据不够轻量,处理起来比较麻烦。

实际上Ajax中的x,有点名不副实。

(2).responseText

实际上,我们在开发的时候,只需要使用responseText就可以。

responseText是指数据以文本字符串的格式从服务端返回到浏览器端。

大家需要明白:数据在浏览器端和服务端进行传输的过程中,都是以文本字符串的形式来进行的。

尽管responseText是字符串,但是也有不同的表现形式:

  • 普遍的纯文本

  • html字符串

  • Json字符串

它是针对,我们在服务端返回字符串的表现形式。

A.普遍的纯文本

这种最简单,就是简单的纯文本。

比如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ajggMKH8-1597495967253)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image109.jpg)]

在xhr中,直接获取,如下:

在这里插入图片描述

拿到之后,根据实际情况来处理。如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kriERGH3-1597495967256)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image113.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VARy9Lud-1597495967257)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image115.jpg)]

B.html字符串

通常是需要在服务端,返回一段拼接好的html字符串。

如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lvkd5btZ-1597495967259)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image117.jpg)]

针对html字符串,我们在浏览器端拿到之后,一般都是使用innerHTML写入DOM,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qv5uPT6s-1597495967260)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image119.jpg)]

效果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mo9aYXNG-1597495967262)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image121.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Mb5OBj5-1597495967263)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image123.jpg)]

C.Json字符串(重点)

Json格式,使用最多的。

请问json是什么?是对象 or 字符串?

是字符串,不是对象。只不过字符串长了一张对象的脸。

两个方面都需要注意:

  • 服务端返回json格式的字符串

  • 浏览器端需要获取,然后将其转成对象

服务端返回json格式的字符串

如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y8irH9m7-1597495967266)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image125.jpg)]

浏览器端需要获取,然后将其转成对象

先获取,并打印:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-irphAN4J-1597495967267)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image127.jpg)]

输出如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VVhCXfmS-1597495967268)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image129.jpg)]

所以,需要对字符串,进行转换,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zhp12WC8-1597495967270)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image131.jpg)]

输出如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q7X4F985-1597495967272)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image133.jpg)]

转成对象之后,使用就方便了。

针对服务端的对象转json字符串,可以用两种简化方式:

  • 直接使用send

  • 使用json

直接使用send,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Klh6RyUA-1597495967285)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image135.jpg)]

实际上,send它会自己去判断参数的格式,然后会写入相应的响应头,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qrLJyeMu-1597495967288)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image137.jpg)]

换言之,send方法会自动将对象转成json字符串,然后传输。

直接使用json方法,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-beuw7AU4-1597495967291)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image139.jpg)]

11.小结

Xhr对象,作用就是用于在浏览器端向服务端悄悄的发送一个http请求,并处理服务端返回的结果,从而实现异步(局部)刷新。

使用思维导图进行小结,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xbWXk0dv-1597495967294)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image141.jpg)]

在使用xhr的时候,一定要结合network面板来查看请求的详情。

12.经典案例—省市区三级联动

(1).目标

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qHQifNOy-1597495967296)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image143.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fr0JfGk7-1597495967298)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image145.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h85M8lsj-1597495967300)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image146.png)]

(2).分析

针对当前效果,有哪些特点,如何实现呢?

首先,整个页面并没有刷新,但是我们确实是获取到了相应的数据。

肯定需要使用ajax来实现。

分析发ajax请求的时机:

  • 页面载入完毕(load)

  • 切换省份的下拉列表中的数据(change)

  • 切换市区的下拉列表中的数据(change)

请问,省市区的数据从何而来呢?

一般而言,数据肯定是存放到数据库中的。

针对一些特殊的数据,我们也可以采取其他的保存方式,比如使用json文件。

如果某个数据,具备如下两个特点:

  • 数据量比较小

  • 数据比较固定的,不会变化

此时,完全可以使用json文件来保存,更加简单和灵活。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iDTxAr6w-1597495967302)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image148.jpg)]

(3).准备工作

第一步,需要准备一个静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gryOMsEX-1597495967304)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image150.jpg)]

第二步,需要提供一个http server,载入静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ktjuDz1c-1597495967305)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image152.jpg)]

启动服务,访问如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RWsCBB8F-1597495967307)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image154.jpg)]

(4).获取所有省份

第一步,在浏览端,发起ajxa请求:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m74fMEh1-1597495967310)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image156.jpg)]

运行,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JnDhhCQl-1597495967312)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image158.jpg)]

说明,请求已经发出了。

第二步,在服务端,处理/provnice的请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kt1hnXDI-1597495967314)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image160.jpg)]

重启,测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5IHvdm6Z-1597495967316)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image162.jpg)]

第三步,将获取的省份写入select中

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MxDtPqas-1597495967319)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image164.jpg)]

查看结果,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SHad1n6y-1597495967322)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image166.jpg)]

技巧:如果想查看本地的josn文件格式,使用firefox浏览器。如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-farn7jC0-1597495967323)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image167.png)]

(5).获取指定省份的所有市区

当用户点击省份的下拉列表,切换省份时,需要发起ajax,获取对应的市区数据。

第一步,注册chang事件,发ajax请求

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jHsvO6K-1597495967324)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image169.jpg)]

需要测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SbiE8omb-1597495967326)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image171.jpg)]

第二步,需要在服务端处理/city的请求

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1MYaX5Av-1597495967328)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image173.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4VYJcfBF-1597495967330)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image175.jpg)]

说明,ok。

第三步,在浏览端,将返回的结果写入select

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w0AQt0pH-1597495967331)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image177.jpg)]

测试,ok,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-repj1BBE-1597495967333)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image179.jpg)]

(6).获取指定市区的所有区县

当用户切换市区select中的市区时,需要载入对应的区县。

第一步,注册chang事件,发ajax请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RGsUdUAV-1597495967334)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image181.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8BfgRCxm-1597495967336)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image183.jpg)]

说明,请求已经发送了。

第二步,在服务端需要处理/country,返回数据

此时,需要注意数据的结构,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KIt2xLwc-1597495967337)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image185.jpg)]

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f3pI1f2s-1597495967339)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image187.jpg)]

测试一下,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DpMUjqrj-1597495967341)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image189.jpg)]

由于直辖市,是没有三级数据的,如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9PQX6pVh-1597495967342)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image190.png)]

所以,我们需要进行一个判断,修改代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzAoWwH5-1597495967343)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image192.jpg)]

再次测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PvFvsJ5s-1597495967345)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image194.jpg)]

说明,ok。

第三步,在浏览器将结果获取到,写入到select中

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2GDk04rf-1597495967347)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image196.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y1RZ5tO5-1597495967348)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image197.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YxaS3RoU-1597495967350)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image198.png)]

最后整体测试,如果已经有了一个三级的区县数据,然后再切换省份的时候,三级的数据仍然还在,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nKxtNyMu-1597495967352)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image199.png)]

这个是不对的,需要完善一下。

实际上,在切换省份数据的时候,需要清空区县的下拉列表。修改如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s4LpyTar-1597495967353)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image201.jpg)]

再次测试,ok。

任务:

  • 检测用户名是否可用

  • 省市区三级联动

四.jQuery中的Ajax方法(重点)

可以回顾一下,前面我们使用xhr对象来实现ajax 的步骤:

  • 创建xhr对象

  • 建立连接

  • 监听状态变化

  • 发送请求

在具体实现的时候,还有一些细节:

  • 针对特殊的符号(&和=)及中文,需要编码

  • Post请求,需要额外的发送一个头,使用setRequestHeader

  • 在ie6/7中,创建xhr对象需要使用AxtiveXObject对象。存在兼容性问题

通过分析,我们发现,使用原生的方式来实现ajax,比较麻烦。在开发中,ajax又是非常常用的技术。为了实现快速高效的开发,通常需要我们对ajax进行封装。

其实,各大优秀的js库,都对ajax进行了封装。比如jquery、prototype、moontools等都提供相应的封装。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZJl0w1g2-1597495967355)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image202.png)]

重点需要掌握如下三个即可:

  • $.get()

  • $.post()

  • $.ajax()

1. . g e t ( ) 和 .get()和 .get().post()

$.get(url, [data], [callback] ,type),GET方式异步请求

$.post(url, [data], [callback] ,type),POST方式异步请求

参数说明如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-33GxXLNV-1597495967357)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image204.png)]

提醒:智能猜测不可靠,必须要自己写上。

(1).使用$.get实现用户名检测

第一步,先准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HSeASuLv-1597495967359)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image206.jpg)]

第二步,提供http server,载入表单页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IzaHxXBY-1597495967360)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image208.jpg)]

启动,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kIjyNjgS-1597495967361)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image209.png)]

第三步,需要引入jquery

首先,创建public目录,将jquery放到其js目录之下,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1H8roic4-1597495967363)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image211.jpg)]

需要使用static中间件托管静态资源,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NV8wdDV0-1597495967364)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image213.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HwMZzg2N-1597495967366)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image215.jpg)]

第四步,编写代码,发ajax请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ehZhtu5C-1597495967368)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image217.jpg)]

测试,查看请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6iqdpWjb-1597495967369)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image219.jpg)]

第五步,在服务端处理/check请求,发回json数据

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7kt3NyiY-1597495967370)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image221.jpg)]

重启服务,测试,ok。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2V5wRnGa-1597495967372)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image223.jpg)]

(2).使用$.post方法实现用户名检测

第一步,准备静态页面,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c23YhjKY-1597495967373)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image225.jpg)]

第二步,载入静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ABc9ejmg-1597495967375)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image227.jpg)]

第三步,使用$.post发ajax请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOJKn4LQ-1597495967376)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image229.jpg)]

第四步,在服务端处理/check请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2pZsuokt-1597495967378)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image231.jpg)]

重启服务,测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-apA6aiwi-1597495967379)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image233.jpg)]

(3).注意点

  • . g e t 和 .get和 .get.post都是异步方式

  • 方法名必须是小写。(js严格区分大小写)

  • 这里的get()和post()是一个全局方法,可以理解为静态方法

  • callback指定的回调函数只有在请求成功时才会执行,如果请求失败(例如找不到页面、服务器错误等)则不作任何处理。

2.$.ajax()

(1).基本用法

用法一:$.ajax( [ settings ] ] )

用法二:$.ajax( url [, settings ] ] ) 1.5新增

具体的参数有如下:

  • url,请求的目标URL,默认为当前页面

  • async,是否是异步请求,默认为true,异步

  • Type,请求类型,可以为POST或GET,默认为GET

  • data,发送到服务器的数据,可以是字符串或对象类型

  • dataType,指定返回数据类型xml/html/script/json/text/jsonp

  • success,指定请求成功后执行的回调函数。

  • error,请求失败时执行的回调函数

  • timeout,设置请求超时的毫秒值

(2).使用$.ajax方法实现用户名检测

第一步,准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xycIsXFZ-1597495967381)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image235.jpg)]

第二步,提供http server,载入表单页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hMzoGc8P-1597495967384)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image237.jpg)]

第三步,使用$.ajax方法发请求,如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y9mcTBdA-1597495967386)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image239.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AhU7OqqC-1597495967387)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image241.jpg)]

第四步,在服务端处理,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EUcBWrww-1597495967389)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image243.jpg)]

(3).其它用法

Timeout参数,用于设定超时时间,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xSNfejhI-1597495967391)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image245.jpg)]

效果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bcl5awkI-1597495967392)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image247.jpg)]

还需要注意,$.ajax方法非常的强大,还有一些相对使用少一些的参数。

在遇到具体的需求时,需要学会快速的查阅手册。

实际上,在jQuery中,针对ajax的封装,$.ajax是核心方法。

其他的一些方法,比如 . g e t 、 .get、 .get.post、 . g e t J S O N 、 .getJSON、 .getJSON.getScript都是调用$.ajax方法的。

换言之, . g e t 、 .get、 .get.post、 . g e t J S O N 、 .getJSON、 .getJSON.getScript是$.ajax方法在特定场景下的快捷方式。

比如:

. g e t , 就 是 在 调 用 .get,就是在调用 .get.ajax方法时,固定了async为true,type为get,去掉error,保留success方法。如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYk7685Y-1597495967394)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image249.jpg)]

针对jquery中封装的ajax功能,只需要掌握一个核心方法 — $.ajax

五.跨域(面试必备)(重点)

重要,很重要,非常重要。

衡量一个前端程序员的水平,可以看它是否掌握了ajax。

衡量一个前端er是否掌握了ajax,就看是否掌握了跨域。

如果你真的开发过项目,你必然会用到ajax,在进行ajax的开发,你必然会遇到跨域问题。

尤其是在前后端分离的开发模式中。

1.什么是跨域

(1).何为跨域?

是指通过js在不同的域之间进行数据传输或通信,如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。

(2).什么情况下有跨域?

三点:

  • 针对不同的域,才会存在跨域问题。比如在localhost域名中,访问自己的,就不存在跨域。

  • 必须是使用js的情况。比如直接在地址栏中输入url,不存在跨域。

  • 必须是在浏览器端。比如在服务端,不存在跨域。

(3).什么样的域才是不同的域?

在一个完整的url中,跨域中的域,包括如下三个方面:

  • 协议,如http/https

  • 主机,有域名和ip两种,如www.baidu.com,127.0.0.1,

  • 端口,如80,8080

如果这三者完全一致,就表示是同一个域,只要有一个不同,就认为是不同的域。

注意关于完全一致,有两个地方需要注意:

  • 主机,就算域名和ip是对应关系,也被认为是不同的。

  • 端口,端口如果省略了,和带端口的也被认为是不同的。如果端口都省略了,是相等的

条件非常的严苛。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hX7UhYt2-1597495967396)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image251.png)]

再比如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GIAxAPom-1597495967398)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image253.jpg)]

(4).同源策略

如果两个页面的协议,域名和端口都相同,则两个页面具有相同的源。

同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能。

MDN 官方给定的概念: 同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

通俗的理解: 浏览器规定,A 网站的 JavaScript,不允许和非同源的网站 C 之间,进行资源的交互,例如:

  • 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

  • 无法接触非同源网页的 DOM

  • 无法向非同源地址发送 Ajax 请求

什么是跨域:

同源指的是两个 URL 的协议、域名、端口一致,反之,则是跨域。

出现跨域的根本原因:浏览器的同源策略不允许非同源的 URL 之间进行资源的交互。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1H0ijHlB-1597495967399)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image255.jpg)]

(5).跨域的演示

第一步,准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nuKrGTKW-1597495967401)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image257.jpg)]

第二步,提供http server,载入静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qtt1ol4B-1597495967402)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image259.jpg)]

第三步,点击按钮时,发ajax请求

当点击button时,向卖座网要数据,

Url如下:http://m.maizuo.com/v4/api/film/now-playing?__t=1505879869719&page=1&count=5

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M7pmAgvS-1597495967403)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image261.jpg)]

请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-57Waul2Z-1597495967405)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image263.jpg)]

这怎么就跨域了?

  • 使用js代码来请求的

  • js代码是浏览器端

  • 是两个不同的域,请求方是http://localhost:4000/,被请求方是http://m.maizuo.com/v4/api/film

所以,刚好就触发了跨域的条件了。

在本地也可以模拟的。

如localhost:3000 --> localhost:4000 也是属于跨域。

(6).为何需要跨域?

基于安全的需要,在web开发中,是不允许跨域访问的。

有一个著名的安全策略 — 同源策略

同源策略的一个目的,就是为了安全起见。

在实际开发,我们又需要跨域去访问。

同源策略,到底是带来安全,还是带来了不便呢?

安全是第一位的,这个策略没有问题的。

但是,我们在开发的时候,有的时候是需要跨域的?

两大场景:

  • 对于大型网站而言,有很多的子域/二级域名,需要恭喜某些数据,需要在不同的域之间请求数据。比如百度,https://www.baidu.com/、http://news.baidu.com/、http://music.baidu.com/、http://image.baidu.com/。

  • 在前后端分离的项目中,将前端的项目和后端提供的api接口部署在不同的域名之下。(尤其是开发过程中)

(7).常见的解决方案

关于跨域,有多大10余种解决方案。

主要是有如下三大方案:

  • Cors

  • 代理

  • Jsonp(重点)

针对每一种解决方案,需要弄清楚:

  • 使用场景

  • 具体如何使用

2.CORS

CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。

(1).什么是cors?

CORS是cross origin resource share,跨域资源共享

我们看从跨域时报错信息来看,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCEClHC5-1597495967407)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image265.jpg)]

说白了,就是localhost:4000域没有权限去异步请求m.maizuo.com/域。

作为m.maizuo.com/域这一方,我们可以去设置谁有权限来访问。

使用场景

针对cors,有前提条件,我们是有权限去编写/修改服务端的代码。或者说服务端的代码就在我们手上。

(2).具体的跨域实现

Cors这种方案,只需要在服务端开发访问权限即可。

在浏览器端不用写任何的代码。

第一步,准备一个静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RDO1CbWx-1597495967410)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image269.jpg)]
·

第二步,在localhost:3000提供http server,载入静态页面

在这里插入图片描述

启动,浏览,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oj5cE6H1-1597495967411)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image271.jpg)]

第三步,在html页面中,向localhost:4000发ajax请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f33dyfdd-1597495967412)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image273.jpg)]

第四步,在localhost:4000端口提供http 服务,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9YaVe8hS-1597495967414)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image275.jpg)]

启动4000端口的服务,再次访问,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zSXlnift-1597495967415)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image277.jpg)]

说明,有跨域限制。

在浏览器端使用js,进行如下的请求

http://localhost:3000/ ----> http://localhost:4000/ajax

第五步,在localhost:4000服务端开发权限

开发权限的代码是固定的,如下:

app.use("*",(req,res,next) => {

  res.setHeader('Access-Control-Allow-Origin', "http://localhost:3000"); 

  res.setHeader('Access-Control-Allow-Credentials', true); //允许携带cookie

  res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');next();

});

开放的域,可以使用*表示所有的域。

增加代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rz2LTfxT-1597495967416)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image279.jpg)]

重启服务,访问如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cdbznhhp-1597495967418)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image281.jpg)]

说明,跨域成功了。

其中,允许的源,可以使用*表示所有的,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PA02OrId-1597495967420)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image283.jpg)]

对于一些公共的开放接口,比如天气预报、地图服务、ip查询、电话号码归属地查询等待,其实都是已经开发给所有用户来使用的。

3.代理

(1).什么是代理?

和日常生活中的代理是一个意思,会涉及到第三方。

使用场景

没有限制,唯有一条,自己必须会一门后端语言。

所谓的代理,是指自己需要去写服务端的代码。

如图:

直接访问,是行不通的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cp47x7kt-1597495967421)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image285.jpg)]

增加一个代理层

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zg7twRAP-1597495967422)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image287.jpg)]

需要注意一点,代理方和访问方需要在同一个域下。

(2).如何实现?

第一步,准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzA5dqcr-1597495967424)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image289.jpg)]

第二步,提供一个http server,载入页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0LDSW4Gn-1597495967425)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image291.jpg)]

启动服务,点击,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7REHlS5P-1597495967427)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image293.jpg)]

说明,有跨域限制。

第三步,增加一个代理层

在浏览器端,将url修改为当前域下的url,将目标地址作为参数传递过去,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dVP6iRI9-1597495967428)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image295.jpg)]

然后,在服务端,就需要处理/proxy的路由,这个路由中,需要获取传递过来的目标url,向其发起http请求,将结果获取到,并返回。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s5Vkf3M2-1597495967430)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image297.jpg)]

重启服务,再次请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NZSq8JDj-1597495967431)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image299.jpg)]

注意:代理方向目标域发http请求,存在跨域吗?

不存在,因为代理方是服务端的js代码。

思考:如果我不能(不会)代理给当前域?还可以使用代理方式吗?

4.Jsonp(重难点)

JSONP**:**出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。

重要程度:*****

(1).什么是jsonp?

Jsonp:json with packing的简写。

将json数据包装起来并返回的一种方式 ----- 协议

需要将jsonp和json区分开:

  • Json是字符串,是数据

  • Jsonp是协议,是传递json数据的方式

Json和jsonp的关系,好比是情报和传递情报的方式。

在使用jsonp实现跨域的时候,它是需要将json数据作为函数的参数(packing的过程),最终在服务端将包装好的字符串作为结果返回给浏览器端。

使用场景

在使用jsonp的时候,需要确保:

  • 有权限去编写服务端的代码

  • 在浏览器端也需要写一些代码

(2).使用jsonp实现跨域之问题

第一步,准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B4p75hkQ-1597495967433)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image301.jpg)]

第二步,提供一个http server,载入静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mL4I416o-1597495967434)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image303.jpg)]

浏览,请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gIW5Ias-1597495967435)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image305.jpg)]

有跨域限制。

第三步,使用jsonp来实现跨域。

jQuery中的ajax方法,针对jsonp有一个封装。通过dataType来设置的。

只需要将dataType设置为jsonp,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O3jKkUV3-1597495967437)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image307.jpg)]

再次访问,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RoJsM1co-1597495967439)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image309.jpg)]

说明有语法错误,这是咋回事呢?

需要通过network分析http协议,我们发现请求已经返回了相应的数据,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XoRAevah-1597495967440)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image311.jpg)]

分析,返回的结果是一个json字符串,不是包装好的jsonp协议的字符串。在浏览器端,它是按照jsonp的协议来解析这个结果,所以语法错误。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p9Qnep9x-1597495967441)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image313.jpg)]

Jsonp返回的不能是json字符串,必须是函数调用的字符串。Json数据作为函数的参数。

如 f1( “{ a : 100, b : 200 }” )

这就需要我们在服务端,返回数据的时候,必须遵循jsonp的协议。

此时,就需要去编写服务端的代码。

(3).使用jsonp实现跨域之解决

要实现jsonp,关键是服务端,必须要以jsonp的协议返回数据。

在localhost:4000中提供一个http服务, 如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iawvfgnR-1597495967443)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image315.jpg)]

在浏览器中,向localhost:4000/ajax发请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FjjJgaqp-1597495967444)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image317.jpg)]

启动服务,再次请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NmKxcP5j-1597495967445)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image319.jpg)]

再次,说明,服务端返回的格式是错误,从而导致解析出错。

关键:服务端,必须要返回一个函数调用的字符串,json数据(字符串)作为函数的参数。

请问:

  • 函数名是什么?

  • 怎么获取的?

再一次使用network分析http,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I0W6iArI-1597495967447)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image321.jpg)]

明明请求的路径是/ajax,我也没有传递任何的data,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKRqCHsn-1597495967449)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image323.jpg)]

实际上,是由于我们设置了dataType为jsonp,所以jQuery就自己随机了一个函数名,将其作为查询字符串传递给服务端了。

在服务端,通过查询字符串来获取即可。编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lL85lJS8-1597495967451)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image325.jpg)]

重启,测试,结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ObwSRjDL-1597495967454)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image327.jpg)]

小结:

在使用jquery的ajax方法实现jsonp跨域,必须:

  • 在浏览器端,设置dataType为jsonp

  • 在服务端,必须以函数调用json字符串的形式返回作为字符串返回

在express中,针对jsonp格式的返回,专门封装了一个jsonp方法,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LRfHrSGJ-1597495967456)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image329.jpg)]

这种使用jsonp方法时候,无需获取函数名,无需转换json,只需要调用jsonp方法,将json数据作为参数即可,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8VlYKlo4-1597495967457)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image331.jpg)]

测试,ok。

实际上,jsopn方法底层就实现了刚才的那两行代码。

(4).jsonp原理剖析

由于jQuery封装好了jsonp的用法,导致很多初学者都错误的理解了jsonp。

实际上,jsonp方法并没有使用xhr对象来完成异步请求。查看network,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Ekzujlq-1597495967459)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image333.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eDkSqmLI-1597495967461)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image335.jpg)]

Jsonp的实现是通过动态的添加script标签从而发送http请求来实现的。

实现如下

第一步,准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8oBshbPA-1597495967466)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image337.jpg)]

第二步,在点击button的时候,需要发起异步请求

不能使用xhr来http请求,也不使用jquery封装的ajax相关方法。

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWeAw3au-1597495967471)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image339.jpg)]

第三步,在3000端口提供http server并托管静态资源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xrZ814M9-1597495967474)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image341.jpg)]

第四步,创建test.js,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PMIg9Lq3-1597495967478)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image343.jpg)]

执行如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OEmReZh3-1597495967487)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image345.jpg)]

说明,这个请求是可以发出的。

第五步,使用addScript发一个普通的请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QFD7jPaU-1597495967489)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image347.jpg)]

只要是script标签的src,写任何地址都可以。能够返回结果并执行,则是另外一回事。

第六步,在服务端,处理/jsonp请求

在返回的时候,返回一段js代码,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xRQNp0Lg-1597495967492)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image349.jpg)]

重启,执行,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AARo3X77-1597495967495)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image351.jpg)]

之所以,可以执行,那是因为,返回的是一段js代码,就好比是直接插入到如下位置:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MyDNzNza-1597495967502)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image353.jpg)]

第七步,需要在服务端返回相应的数据,在浏览端获取并操作

目前我们是直接在服务端输出js代码,在浏览器端我们就不能拿到返回的结果,进行二次处理。换言之,浏览器端是被动的执行js代码,而不是获取返回的结果,主动的去操作。

在浏览器定义一个函数,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DR3JRohK-1597495967503)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image355.jpg)]

需要告诉服务端,我定义的函数叫什么名字?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZXeYrHNk-1597495967505)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image357.jpg)]

如此一来,就可以在服务端获取这个函数的名字,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w6uqIEzP-1597495967507)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image359.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ORUBz5b7-1597495967509)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image361.jpg)]

实际上,在服务端返回的通常是json字符串,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AA3MQuVV-1597495967512)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image363.jpg)]

测试如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-taEv9jNM-1597495967514)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image365.jpg)]

再次回顾jsonp的概念:

将json数据包装起来并返回的一种方式 ----- 协议

在使用jsonp实现跨域的时候,它是需要将json数据作为函数的参数(packing的过程),最终在服务端将包装好的字符串作为结果返回给浏览器端。

(5).jquery中jsonp相关设置

在jquery中的ajax方法中,和jsonp相关的还有如下两个设置:

默认如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p4bskKtT-1597495967518)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image369.jpg)]

可以自己设置,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DUs79JSq-1597495967521)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image371.jpg)]

测试如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5MEyu7Dg-1597495967522)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image373.jpg)]

但是,需要注意,res的jsonp方法,要求回调函数名必须是callback,否则出错,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-csluE48Q-1597495967525)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image375.jpg)]

三种方式都已经讲解完毕。

在实际开发的时候,具体使用哪种方式,需要看情况来定。

作为前端,有时候是主动的,有时候是被动的。

而且,可以将cors和代理结合到一起,可以天下无敌。(大家自己写一写)

5.结合webpack

webpack是非常牛x的前端构建工具。

现在几乎所有的前端开发,都会用到webpack,尤其基于框架(vue、react、angular)的开发。

Webpack安装了一个第三方模块 – http-proxy-middleware,也可以实现跨域,只需配置即可。(后面补充)。

六.分页进化史(典型开发场景)(重点)

1.不分页显示

第一步,准备数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tKK9dymc-1597495967527)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image377.jpg)]

使用insert命令插入到mongodb中,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ekj51ivr-1597495967529)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image379.jpg)]

第二步,编写服务端代码,提供http server,获取数据,渲染到页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KuWa3Bh1-1597495967532)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image381.jpg)]

第三步,在视图页面中,使用ejs模板语法输出数据即可

浏览,效果如下:

浏览,效果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-67Z6p0Lg-1597495967535)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image385.jpg)]

任务:

  • 实现仿google suggest

  • 三种跨域,都需要敲2~3遍

  • jsonp的原理,一定要多敲两遍,理解

  • 不分页显示博客

  • 分页显示、ajax分页都可以尝试着做

2.传统分页显示

针对前面的数据展示方式,肯定是有问题的:

  • 用户体验不好

  • 性能有影响

针对大量的数据,通常需要使用分页的方式来展示。如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WnsNWTkk-1597495967538)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image387.jpg)]

所以,需要对我们的博客页面进行改造,添加分页功能。

(1).分页原理

从两个方面:

  • 数据库查询

  • 传递分页参数

A.从数据库查询的角度来分析

设定,每一页显示5条,使用pagesize表示,当前是第几页使用page表示

第一页,db.blog.find({},{_id:0}).limit(5).skip(0)

第二页,db.blog.find({},{_id:0}).limit(5).skip(5)

第三页,db.blog.find({},{_id:0}).limit(5).skip(10)

第n页,db.blog.find({},{_id:0}).limit(pagesize).skip((page - 1)* pagesize)

B.传递分页参数

通过上面的分析,我们需要获取的参数是当前页数。这个是变化的,和用户的操作相关。

默认是第一页,其它的页面,需要使用查询字符串来传递的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Vp6ZYxI-1597495967540)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image389.jpg)]

分两步实现:

  • 手动传递参数,实现分页查询

  • 提供分页信息及操作

(2).手动传递参数实现分页查询

第一步,提供一个http server,实现分页查询

比如第一页:http://localhost:3000

第二页:http://localhost:3000?page=2

第三页:http://localhost:3000?page=3

查询语句为:db.blog.find({},{_id:0}).limit(pagesize).skip((page - 1)* pagesize)

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0LXoXap6-1597495967544)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image391.jpg)]

第二步,在视图页面中使用ejs来输出数据

这个视图和前面的那个是差不多的,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-leJjsK8h-1597495967546)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image393.jpg)]

启动服务,浏览如下:

[
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Y61Uyd2-1597495967550)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image397.jpg)]

针对page参数,需要做一些处理和限定,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3IZgk78e-1597495967551)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image399.jpg)]

(3).提供分页信息及操作

通常,需要在列表的底部,提供分页的信息及操作,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vl16GOq1-1597495967553)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image401.jpg)]

第一步,先在页面中增加一个固定的分页信息,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yGJt1eJv-1597495967555)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image403.jpg)]

显示如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9GUKX7Ym-1597495967556)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image404.png)]

现在,需要将x、y、a和b变成活的。

第二步,在服务端获取这些值,传递到模板页面

我们已经有了当前页数,和每页显示的条数,就剩下总的记录数和总的页数。

关键是要获取总的记录数,需要查询数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KVfY0Yrd-1597495967558)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image406.jpg)]

需要再次查询数据库,如下:

第三步,在视图页面中输出分页信息,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RWxvwLfJ-1597495967561)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image410.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q3VKvFmZ-1597495967563)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image412.jpg)]

第四步,实现上一页/下一页的跳转

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mzh2qkqx-1597495967565)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image414.jpg)]

3.Ajax普通分页

(1).传统分页的问题

在刚才代码中,增加一点点内容,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M3ic6EXI-1597495967566)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image416.jpg)]

在点击上一页/下一页的时候,查看时间的变化,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BhuiIKpq-1597495967568)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image418.jpg)]

时间总是在变化,说明整个页面都进行了刷新操作。

在实际的web中,有很多时候,列表只是页面的一小部分,比如京东的商品详情页:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pf0zTnml-1597495967572)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image420.jpg)]

如果这个翻页操作是整体刷新,会怎么样?

  • 用户体验下降

  • Web的性能受到影响

需要使用局部刷新技术来改造分页显示。

接下来,使用ajax来实现分页。

如果使用ajax方式,获取数据的方式发生了变化:

  • 传统方式,在服务端查询,然后分配到模板页面

  • Ajax方式,在浏览器端发http请求,服务端返回,在浏览器端写dom即可

这就意味着,在ajax方式下,不需要使用ejs。

(2).具体实现

第一步,准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dwshechz-1597495967573)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image422.jpg)]

第二步,提供一个http server,载入静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qa1A4jXb-1597495967575)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image424.jpg)]

启动服务,浏览,如下:

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mOtaDj93-1597495967577)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image426.jpg)]

第三步,在浏览器端发起ajax请求,获取数据

在基于ajax的方式中,第一次显示的数据也是通过ajax来实现的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Up9DVqoY-1597495967579)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image428.jpg)]

浏览,查看xhr请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GOBHdgXu-1597495967582)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image430.jpg)]

说明请求已经发送了。

第四,在服务端处理请求,返回数据

这个和刚才的获取数据是一样的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0jU36nH4-1597495967586)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image432.jpg)]

同时,需要修改一下浏览端的代码,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1XCaXowA-1597495967589)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image434.jpg)]

启动,输出如下:

[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pWIsewcV-1597495967595)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image438.jpg)]

第五步,显示分页信息

修改分页信息的结构,如下:

在这里插入图片描述

在ajax返回结果的时候,写dom操作,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SS2sN4bg-1597495967599)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image440.jpg)]

显示,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I47WEEA0-1597495967601)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image442.jpg)]

第六步,实现上一下/下一页操作

需要对超链接注册时间,发ajax请求即可。

增加id属性,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nVxesKQf-1597495967602)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image444.jpg)]

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QF3jqA1Q-1597495967605)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image446.jpg)]

测试,ok。

4.Ajax分页之加载更多

(1).分析

分析加载更多的特点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vi24UlDk-1597495967608)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image448.jpg)]

意味着,只能前进,不能后退。

所以,在这种模式下,只能使用累加的方式,也就是:

  • 默认显示第一页中的记录,比如5条

  • 后续的点击加载更多,就将固定的记录追加到页面中

(2).具体实现

第一步,准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8p9lwNRi-1597495967610)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image450.jpg)]

第二步,提供一个http server,载入静态页面,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GuUYeVNw-1597495967612)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image452.jpg)]

启动,浏览如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zX6WhQdE-1597495967613)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image454.jpg)]

第三步,在页面载入成功的时候,发ajax请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UFmZDWm6-1597495967615)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image456.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hoxt7xAk-1597495967617)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image458.jpg)]

第四步,在服务端处理/blog请求

在这里插入图片描述

重启,测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YyMtvqaE-1597495967621)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image462.jpg)]

第五步,浏览器端处理返回的结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EbCunI79-1597495967623)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image464.jpg)]

注意,第一次是载入页面成功的时候,发ajax请求。

结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qCWDnFF4-1597495967626)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image466.jpg)]

第六步,注册点击事件,发ajax请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P07t9AUn-1597495967628)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image468.jpg)]

测试,ok。

但是这个效果不理想。需要处理细节。

在服务端模拟一个延时操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kq3BBuKB-1597495967630)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image470.jpg)]

此时,我们应该提供一个视觉反馈。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rI4KHW89-1597495967632)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image472.jpg)]

测试,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q9aztoHF-1597495967634)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image474.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WeFBU8Fr-1597495967635)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image476.jpg)]

还有一点,如果没有数据了,应该提示用户。增加代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AtwyQPBB-1597495967637)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image478.jpg)]

测试,ok。

还需要完善一点,在正在加载的时候,不能发请求。有两种解决方案:

  • 在发请求的过程中,禁用按钮

  • 在在请求的过程中,允许点击,但是不发ajax请求

此处,采用第二种。增加一个开关,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yPQcMMjV-1597495967639)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image480.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DhUZEHZY-1597495967641)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image482.jpg)]

测试,ok。

5.Ajax分页之滚动加载

在今天的web当中,分页显示已经普遍使用滚动加载。

(1).分析

和加载更多有很多相似之处。

第一次是页面载入成功时,就发一次ajax请求,获取数据写入页面。

后续的是在页面到达底部时,再发ajax请求,获取数据,追加到页面中的。

不同之处:

原来的方式,是在按钮上点击的时候,触发ajax请求

现在的方式,在页面滚动到底部的时候,触发ajax请求。

关键在于,如何知道 页面滚动到底部。

在滚动的场景中,有如下三个高度:

  • 可视窗口的高度

  • 文档的高度

  • 滚动条卷起的高度(滚动的距离)

在jQ中,封装了如下方法:

滚动条滚动的高度— $(window).scrollTop()

窗口的可视高度 ---- $(window).height()

文档的高度---- $(document).height()

可以写测试页面,编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qaU9z3SO-1597495967643)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image484.jpg)]

在滚动的时候,查看输出,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tor65Ex1-1597495967644)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image485.png)]

条件就出来了。

st + ch == dh,就说明到达底部了。

(2).具体实现

第一步,准备静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y22oFEju-1597495967649)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image489.jpg)]

第二步,提供一个http server,载入静态页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qBxfwD6Y-1597495967650)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image491.jpg)]

启动服务,浏览如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kcaZtmKU-1597495967652)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image493.jpg)]

第三步,封装一个方法,用于实现ajax请求数据

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WiczmUd8-1597495967654)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image495.jpg)]

第四步,在服务端需要处理/blog请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dGUxY0c8-1597495967656)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image497.jpg)]

测试,ok。

第五步,需要注册滚动事件,判断是否滚动到底部,并发ajax****请求

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ooQmwbpE-1597495967658)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image499.jpg)]

测试,ok。

第六步,需要添加视觉反馈,提供良好的用户体验。

先准备一张图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DHPpaY6h-1597495967660)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image501.jpg)]

在发请求的时候,需要显示这张图片,在加载完毕时需要隐藏这张图片。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7G0s3YE-1597495967662)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image503.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1voAQ9qT-1597495967664)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image505.jpg)]

节流函数。(自己加一下)

所谓的滚动加载,其实就是分页的高级形式,只是在展示层面有变化,其本质仍然是分页显示数据。

七.form表单强化和前端模板引擎(了解)

1.form表单强化

表单在网页中主要负责数据采集功能。HTML中的标签,就是用于采集用户输入的信息,并通过标签的提交操作,把采集到的信息提交到服务器端进行处理。

2.标签的属性

标签用来采集数据,标签的属性则是用来规定如何把采集到的数据发送到服务器。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210105120547808.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2NDEyODI1,size_16,color_FFFFFF,t_70)

3.Action

action 属性用来规定当提交表单时,向何处发送表单数据。

action 属性的值应该是后端提供的一个 URL 地址,这个 URL 地址专门负责接收表单提交过来的数据。

当 表单在未指定 action 属性值的情况下,action 的默认值为当前页面的 URL 地址。

注意:当提交表单后,页面会立即跳转到 action 属性指定的 URL 地址

4.Target

target 属性用来规定在何处打开 action URL。

它的可选值有5个,默认情况下,target 的值是 _self,表示在相同的框架中打开 action
在这里插入图片描述

5.Method

method 属性用来规定以何种方式把表单数据提交到 action URL。

它的可选值有两个,分别是 get 和 post。

默认情况下,method 的值为 get,表示通过URL地址的形式,把表单数据提交到 action URL。

注意:

  • get 方式适合用来提交少量的、简单的数据。

  • post 方式适合用来提交大量的、复杂的、或包含文件上传的数据。

  • 在实际开发中, 表单的 post 提交方式用的最多,很少用 get。例如登录、注册、添加数据等表单操作,都需要使用 post 方式来提交表单。

6.Enctype

注意:

在涉及到文件上传的操作时,必须将 enctype 的值设置为 multipart/form-data

如果表单的提交不涉及到文件上传操作,则直接将 enctype 的值设置为 application/x-www-form-urlencoded 即可!

7.表单的同步提交及缺点

通过点击 submit 按钮,触发表单提交的操作,从而使页面跳转到 action URL 的行为,叫做表单的同步提交。

表单同步提交的缺点:

  • 表单同步提交后,整个页面会发生跳转,跳转到 action URL 所指向的地址,用户体验很差。
  • 表单同步提交后,页面之前的状态和数据会丢失。

如果使用表单提交数据,则会导致以下两个问题:

  • 页面会发生跳转

  • 页面之前的状态和数据会丢失

解决方案:表单只负责采集数据,Ajax 负责将数据提交到服务器。

8.渲染UI结构时遇到的问题

通过字符串拼接的形式,来渲染UI结构。

如果UI结构比较复杂,则拼接字符串的时候需要格外注意引号之前的嵌套。且一旦需求发生变化,修改起来也非常麻烦。

模板引擎,顾名思义,它可以根据程序员指定的模板结构和数据,自动生成一个完整的HTML页面。

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FX5cNxWV-1597495967669)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image511.jpg)]

模板引擎的好处

  • 减少了字符串的拼接操作

  • 使代码结构更清晰

  • 使代码更易于阅读与维护

9.art-template简介

art-template 是一个简约、超快的模板引擎。中文官网首页为:

http://aui.github.io/art-template/zh-cn/index.html

10.art-template的使用步骤

  • 导入 art-template

  • 定义数据

  • 定义模板

  • 调用 template 函数

  • 渲染HTML结构

标准语法:

art-template 提供了 {{ }} 这种语法格式,在 {{ }} 内可以进行变量输出,或循环数组等操作,这种 {{ }} 语法在 art-template 中被称为标准语法。

标准语法之输出:

  • {{value}}

  • {{obj.key}}

  • {{obj[‘key’]}}

  • {{a ? b : c}}

  • {{a || b}}

  • {{a + b}}

在 {{ }} 语法中,可以进行变量的输出、对象属性的输出、三元表达式输出、逻辑或输出、加减乘除等表达式输出。

标准语法之原文输出:

{{@ value }}

如果要输出的 value 值中,包含了 HTML 标签结构,则需要使用原文输出语法,才能保证 HTML 标签被正常渲染。

标准语法之条件输出:

如果要实现条件输出,则可以在 {{ }} 中使用 if … else if … /if 的方式,进行按需输出。

{{if value}} 按需输出的内容 {{/if}}

{{if v1}} 按需输出的内容 {{else if v2}} 按需输出的内容 {{/if}}

标准语法之循环输出:

如果要实现循环输出,则可以在 {{ }} 内,通过 each 语法循环数组,当前循环的索引使用 $index 进行访问,当前的循环项使用 $value 进行访问。

{{each arr}}

{{KaTeX parse error: Expected 'EOF', got '}' at position 6: index}̲} {{value}}

{{/each}}

标准语法之过滤器:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ct0Uf0ab-1597495967671)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image513.jpg)]

过滤器的本质,就是一个 function 处理函数。

{{value | filterName}}

过滤器语法类似管道操作符,它的上一个输出作为下一个输入。

定义过滤器的基本语法如下:

template.defaults.imports.filterName = function(value){/return处理的结果/}

注册时间:{{regTime | dateFormat}}

template.defaults.imports.dateFormat = function(date) {

var y = date.getFullYear()

var m = date.getMonth() + 1

var d = date.getDate()

return y + ‘-’ + m + ‘-’ + d // 注意,过滤器最后一定要 return 一个值

}

八.新的ajax方式(了解)

(1).为何需要新的ajax方式

由于近几年来,前端的开发方式发生了变化。

主要是体现:

  • 前后端分离

  • mv*框架的大力发展

比如,现在典型的前端,需要掌握vue.js/recat.js/angular等框架来进行开发。

针对vue.js/react.js/angular,有如下特点:

  • 提倡数据驱动DOM

  • 遵循前后端分离开发思想

在数据驱动DOM的开发模式中,我们再也不需要进行dom操作了。只需要去设置状态即可,界面会根据状态来进行相应的显示(本质是dom操作由框架本身来实现的)。因此,在使用vue.js/react.js/angular进行开发的时候,就不再需要jQuery了。

在前后端分离开发思想中,我们作为前端,必须要使用ajax****方式去异步获取数据并渲染。

在使用ajax的适合,我们有如下两种选择:

  • 使用原生的xhr对象来实现

  • 使用jQuery封装的ajax相关方法

如果使用原生的xhr对象来实现,需要编写复杂的代码,还需要考虑浏览器的兼容性,注意细节等,对程序员不友好。

如果使用jQuery封装的ajax相关方法,完全可以避免原生方式的缺点。

我们只是为了使用ajax,然后引入了一个巨大的jQuery,有点不划算。对性能有所损失。对用户不友好。

并且,这两种方式,功能还不够强大。

(2).有哪些新的ajax方式

因此,针对ajax,就出现了一些新的方式:

+fetch

  • axios

Fetch,是被誉为下一代ajax的标准,在不久的将来,就会取代XMLHttpReqeust对象。

Axios,则是针对ajax进行的一个高度封装的库,非常小,功能比较完善。

新的方式,只专注于ajax,没有其他功能,可以在任何项目中来使用。

(3).Fetch

Fetch,是被誉为下一代ajax的标准,在不久的将来,就会取代XMLHttpReqeust对象。

http://caniuse.com/#search=fetch

大部分浏览器本身就支持。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DWyBNkfb-1597495967672)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image515.jpg)]

在实际开发时,可以安装一些相应的fetch库。

Github地址:https://github.com/github/fetch

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uwkewJ4S-1597495967673)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image516.png)]

使用非常的简单,基本的api,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4EfIB6Vq-1597495967675)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image518.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xd60nY7d-1597495967676)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image520.jpg)]

使用fetch,获取本地的数据,

在本地启动一个http server,在4000端口,提供一个服务,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pq8MddX-1597495967678)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image522.jpg)]

编写代码,获取数据,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2uelFOA0-1597495967680)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image524.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lUTru9M3-1597495967681)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image526.jpg)]

如果没有设置cors跨域,那么我们在使用fetch的时候,也会有跨域问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-prYWIRol-1597495967682)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image528.jpg)]

当前的文件的url是:

file:///E:/web07/ajax/code/37.%E4%BD%BF%E7%94%A8fetch%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE.html

目标的ulr是:http://localhost:4000/ajax

协议就不相同,所以也是跨域。

注意,浏览器有缓存,所以在开发的时候,有时候需要清除缓存。

可以使用强制刷新,ctrl + f5

(4).Axios

Github地址:https://github.com/mzabriskie/axios

中文手册:https://www.kancloud.cn/yunye/axios/234845

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和node.js 中。

Axios既可以在浏览器端使用,也可以在服务端来使用。

特性:

  • 从浏览器中创建 XMLHttpRequests

  • 从 node.js 创建 http 请求

  • 支持 Promise API

  • 拦截请求和响应

  • 转换请求数据和响应数据

  • 取消请求

  • 自动转换 JSON 数据

  • 客户端支持防御 XSRF

支持度:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mgDKA2BG-1597495967684)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image530.jpg)]

安装有如下两种方式:

  • 使用script的方式引入

  • 基于模块化的开发,使用npm方式安装并引入

Api:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1GAdctgr-1597495967686)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image532.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LENiD2rC-1597495967687)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image533.png)]

还是获取localhost:4000/ajax的数据,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bVySF8Zj-1597495967689)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image535.jpg)]

测试,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gEBlI6mP-1597495967691)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image537.jpg)]

看本质,还是xhr请求,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pjqifauO-1597495967692)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image539.jpg)]

(5).小结

针对ajax开发,我们拥有了如下四种方案:

  • 原生xhr

  • 使用jQ封装的ajax方法

  • Fetch

  • Axios

在开发的时候,原生xhr对象基本不用。

其余三种基本上都会碰到

如果是传统的前端开发,一般都会使用jQ封装的ajax方法。

如果是基于vue.js开发,一般会axios,也可以使用fetch。

如果是基于react.js开发,一般会使用fetch,也可以使用axios

如果是基于angular开发,自己有封装好的http方法。当然也可以使用fetch和axios。

不管是哪一种方式,都会碰到跨域问题,解决的方案有如下几种:

  • cors

  • 代理

  • Jsonp

  • Chrome浏览器的cors插件

  • Webpack的配置

九.Promise(重点)

1.什么是promise

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HI93kSEU-1597495967694)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image541.jpg)]

本意是承诺。

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了promise对象。

所谓promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

如何理解:

  • 没有异步就不需要promise。

  • Promise本身不是异步,只是我们去编写异步代码的一种方式

2.promise的典型用法

在学习promise的时候,一定要站在两个角度看待promise:

  • 站在使用者的角度

  • 站在定义者的角度

在如下几个地方,都必须使用promise的写法:

  • Fetch

  • Axios

典型写法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F0ANh053-1597495967696)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image543.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mlUAbsrA-1597495967697)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image545.jpg)]

特点是:

  • then方法通常是表示异步操作成功时的回调,catch方法通常是表示异步操作失败时的回调

  • 在调用的时候then在前后,catch在后

  • then方法可以调用多次,前一个then的返回值,会作为后一个then的参数。

  • 支持链式调用

其它的一些异步操作,我们也可以使用promise的用法。

比如,jquery中的ajax方法,也支持promise的用法,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NBhBpuPP-1597495967699)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image547.jpg)]

注意:和fetch/axios不同的是,此处使用done方法来替代then方法。

3.为何需要promise

再次声明:

  • 没有异步,就不需要promise

  • Promise本身不是异步的,只是编写异步代码的一种优雅方式。

需要来看一段典型的异步代码 — 异步读取多个文件

首先,创建4个文本文件,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KbpqqfG6-1597495967701)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image549.jpg)]

编写代码,使用node的fs模块来读取文件,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ajenP3QB-1597495967702)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image551.jpg)]

功能没有任何问题,但是这个写法比较讨厌— 这就是臭名昭著的回调地狱(callback hell)。

针对这个写法,非常的糟糕,需要有一种机制,让这个写法变得更加优雅一些。

所以,在前端社区中,就有一些牛人,纷纷提供了一些新的写法,以避免回调地狱。

后来,es6就在这些基础之上,将Promise直接纳入的规范。从而成为es6中的标准用法。

4.promise A+规范

由于promise本身出自于民间,就有很多不同的实现版本。

Es6将promise纳入自己规范的时候,也遵循了一个相应的标准 – Promise A+规范。

将其归纳为4321规范。

  • 4:4大术语

  • 3:3种状态

  • 2:2种事件

  • 1:1个对象

(1).4大术语

一定要结合异步操作来理解。

既然是异步,这个操作需要有个等待的过程,从操作开始,到获取结果,有一个过程的。

解决(fulfill):指一个 promise 成功时进行的一系列操作,如状态的改变、回调的执行。虽然规范中用 fulfill 来表示解决,但在后世的 promise 实现多以 resolve 来指代之。

拒绝(reject):指一个 promise 失败时进行的一系列操作。

终值(eventual value):所谓终值,指的是 promise 被解决时传递给解决回调的值,由于 promise 有一次性的特征,因此当这个值被传递时,标志着 promise 等待态的结束,故称之终值,有时也直接简称为值(value)。

据因(reason):也就是拒绝原因,指在 promise 被拒绝时传递给拒绝回调的值。

(2).3种状态

在异步操作中,当操作发出时,需要处于等待状态

当操作完成时,就有相应的结果,结果有两种:

  • 成功了

  • 失败了

一共是3种状态,如下:

  • 等待态(Pending)

  • 执行态(Fulfilled)

  • 拒绝态(Rejected)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bGvneU21-1597495967703)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image553.jpg)]

针
对每一种状态,有一些规范:

等待态(Pending)

处于等待态时,promise 需满足以下条件:

  • 可以迁移至执行态或拒绝态

执行态(Fulfilled)

处于执行态时,promise 需满足以下条件:

  • 不能迁移至其他任何状态

  • 必须拥有一个不可变的终值

拒绝态(Rejected)

处于拒绝态时,promise 需满足以下条件:

  • 不能迁移至其他任何状态

  • 必须拥有一个不可变的据因

(3).2种事件

针对3种状态,只有如下两种转换方向:

  • pending --> fulfilled

  • pendeing --> rejected

在状态转换的时候,就会触发事件。

如果是pending --> fulfiied,就会触发onFulFilled事件

如果是pendeing --> rejected,就会触发onRejected事件

(4).1个对象

就是指promise对象

5.promise的基本用法

(1).实例化Promise对象

在es6中,本身提供了一个Promise的构造器,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a4zvK44B-1597495967705)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image554.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yoVsGZMS-1597495967706)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image556.jpg)]

可以使用new 直接创建一个,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-al2h7lvF-1597495967709)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image558.jpg)]

执行,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N8DQ3mVH-1597495967711)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image560.jpg)]

之所以报错,是因为这个Promise构造器,必须要传递一个参数。

构造器的参数,是一个回调函数,包含两个参数:

  • resolve

  • reject

编写如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vmkplg6P-1597495967712)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image562.jpg)]

再次查看,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wPexp6Ca-1597495967714)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image564.jpg)]

说明,我们已经创建好了Promise对象,当前这个对象处于 pending 状态。

回调函数中的两个参数,其作用就是用于转换状态:

  • resolve,将状态从pending --> fullFilled

  • reject,将状态从pending --> rejected

直接使用函数调用的方式来进行转换,在转换的时候必须要传递相应参数

Resolve函数的参数,就是指 终值(value)

Reject函数的参数,就是指 据因(reason)

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JVUfHIXC-1597495967715)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image566.jpg)]

查看如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-awHSHdJv-1597495967716)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image568.jpg)]

其中,resolved 就是 fulFilled

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k9BPTAfz-1597495967718)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image570.jpg)]

查看,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61fdywIH-1597495967720)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image572.jpg)]

关于Promise的创建工作,已经完成了。

在创建promise对象,只需要根据需求,转换状态即可。无非就是调用两个函数:

  • resolve,传递value

  • reject,传递reason

比如,可以编写如下代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EbBC9UjP-1597495967721)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image574.jpg)]

执行,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HnV24rMJ-1597495967723)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image576.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iAwnkeip-1597495967724)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image578.jpg)]

(2).then方法

思考,针对刚才的代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X71cdbto-1597495967726)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image580.jpg)]

如何获取这里的终值 ok 或者 据因 error呢?

此时,就需要 利用 事件机制。

针对3种状态,只有如下两种转换方向:

  • pending --> fulfilled

  • pendeing --> rejected

在状态转换的时候,就会触发事件。

如果是pending --> fulfiied,就会触发onFulFilled事件

如果是pendeing --> rejected,就会触发onRejected事件

在调用resolve方法或者reject方法的时候,就一定会触发事件。

需要注册onFulFilled事件 和 onRejected事件

针对事件的注册,Promise对象提供了then方法,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZDX3mKFJ-1597495967727)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image582.png)]

针对 onFulFilled,会自动提供一个参数,作为终值(value)

针对 onRejected,会自动提供一个参数,作为据因(reason)

注册事件,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEXYJ0kJ-1597495967730)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image584.jpg)]

再次调用:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UrGIKHfF-1597495967731)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image585.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UuIAClDs-1597495967733)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image587.jpg)]

(3).关于promise的典型定义

Promise主要是解决异步代码的编写方式。

案例1**:读取文件操作**

原来的写法,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jDBPLbME-1597495967735)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image589.jpg)]

使用promise的写法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4hXN9m1R-1597495967737)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image591.jpg)]

案例2:根据随机数返回结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mYn9Xyyx-1597495967739)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image593.jpg)]

执行,如下:

在这里插入图片描述

在这里插入图片描述

真正的promise****定义方式

回到读取文件案例,需要再读取b.txt,如何实现?

需要将读取文件的操作,封装为一个函数,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nWpZ1HIf-1597495967743)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image599.jpg)]

在开发的时候,我们定义promise对象,必须是要作为函数的返回值。

任务:

  • 分页的各种形式

  • 可以使用iscroll插件、minirefresh 实现移动端的上拉加载,下拉刷新

  • Promise需要好好消化一下

(4).catch方法

Promise对象,有一个then,如下:

promise.then(onFulfilled, onRejected)

需要写两个回调。其中第二个回调表示 从pending —> rejected 时的回调。

由于这种写法,辨识度不高。

Promise就提供了一个catch方法,用于注册 onRejected回调。

使用如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sbVRXpGc-1597495967745)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image601.jpg)]

在这里要明白两件事情:

  • catch其实是then的简写,then(null,callback),如下:

在这里插入图片描述

  • then方法调用之后,仍然返回的是promise对象,所以可以链式调用,如下:

在这里插入图片描述

所以,我们在使用promise对象时,一般这么描述,异步操作成功的时候,走then,失败的时候就走catch。

(5).then方法的链式调用

在fetch的代码中,有如下写法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Va3Bl8op-1597495967750)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image607.jpg)]

也就说,then方法后面继续的调用then方法,这就是then的链式调用。

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HW8D2NuY-1597495967751)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image609.jpg)]

重点是p2**,then方法返回的是一个promise对象,但它是一个新的promise对象,不再是原来的promise对象**,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oMDCcbMi-1597495967753)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image611.jpg)]

所以,then方法可以实现链式调用。

在then方法的链式调用中,有一个非常重要的特点:

前一个then方法的返回值,或作为下一个then方法的参数(普通参数,promise****对象例外)

如果返回的是promise对象,就作为下一次调用then方法的promise对象。

编写代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5uov4sUQ-1597495967754)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image613.jpg)]

此时,就应该联想到在使用fetch的时候,如下代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mduWpv7q-1597495967755)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image615.jpg)]

注意:这个then方法中回调函数的return 返回值,和then****方法本身的返回值是两码事。

到这儿,我们就可以解决回调地狱的糟糕写法问题。

原来的写法,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FoJqR1vc-1597495967758)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image617.jpg)]

都是通过回调来实现的,层层嵌套,不优雅。

现在,我们就可以通过promise改写,使其使用同步的一种方式来编写代码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zf8AWnst-1597495967760)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image619.jpg)]

如何理解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oUPPA41s-1597495967761)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image621.jpg)]

这种写法,上一个then的返回值,就直接等于下一个then 的参数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UL3d5V6t-1597495967763)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image623.jpg)]

在这种写法中,返回的是一个promise对象,这个对象就作为下一次调用then方法promise对象。

最后,当有多个then方法调用的时候,需要将catch放到最后,从而捕获任何一个then方法的错误。如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-reYfLrkN-1597495967765)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image625.jpg)]

(6).all和race方法

all:所有

race:竞赛

all和race都是Promise构造器对象的静态方法。直接使用Promise调用,如下:

  • Promise.all()

  • Promise.reace()

返回值都是promise对象。

当有多个异步操作的时候,经常会有如下两种需求:

  • 确保所有的异步操作完成之后,才进行某个操作,只要有一个失败,就不进行

  • 只要有一个异步操作文章,就里面执行某个操作。

有点类似于运算符中的 逻辑与 和 逻辑或。

all使用如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WpcNA9En-1597495967766)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image627.jpg)]

如果有错误,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2fv1WAAM-1597495967768)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image629.jpg)]

race****的用法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fJvqMR5K-1597495967770)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image631.jpg)]

比如,在一个页面中,需要发多个ajax请求,必须保证所有的数据都返回,才显示页面,可以使用all。

又比如,异步获取一个数据,这个数据有多个接口,只要有一个成功即可,此时就可以race。

6.使用第三方的Promise库

对开发中使用promise进行小结:

没有异步,就不需要promise。

不使用promise,其实也是可以解决异步编程的问题。使用promise,会使异步的编码变得更加优雅,功能会更强。

在进行promise编程的使用,有如下两个场景:

  • 直接使用别人封装好的promise对象,比如fetch、axios

  • 需要自己封装promise对象

注意:axios和fetch必须使用promise方式,如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7HoCGQ9V-1597495967772)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image633.jpg)]

针对自己封装promise对象,又可以有如下两种方式:

  • 自己封装

  • 可以使用第三方的promise库

比如,针对第三方的promise库,有两个知名的库:

  • bluebird

  • q.js

可以利用bluebird 和 q.js 快速的生成promise对象。

以bluebird为例,在服务端演示其用法。

http://bluebirdjs.com/docs/getting-started.html

第一步,安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-umKF2r1W-1597495967774)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image635.jpg)]

第二步,使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nWHOH308-1597495967776)(file:///C:/Users/17454/AppData/Local/Temp/msohtmlclip1/01/clip_image637.jpg)]

  • 6
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值