##AJAX编程
之前学习了什么
在之前的学习过程中,我们很专注,没有关心这些东西在整体中是什么角色,起到什么作用。这里我们是时候总结一下我们之前学过了的内容:
- 网页开发技术(硬性)
- HTML —— 网页内容结构(GUI)
- CSS —— 网页外观样式(GUI)
- JavaScript —— 编程语言(可以用于调用浏览器提供的 API)
- Web APIs —— 网页交互(界面功能)
- jQuery —— 便捷手段(糖果而已,不是必要的)
- node基础 —— 了解前台端交互流程
- 编程能力 / 编程思想 / 解决问题的思路(软性)
- 我要做什么(我要得到什么),我目前有什么(我能拿到什么)
至此,我们已经可以独立完成网页开发了,具体能完成的东西就是一个一个的网页,而且还能给这个页面加上一些动态的交互。但是这距离成为一个网站还有一些路要走。
还需要学习什么?
想要完成完整的 Web 网站,还需要学习什么?
- HTTP(浏览器与服务端的通讯协议)
- AJAX(浏览器与服务端的数据交互方式)
- 数据库操作(服务端存储数据方式)
- 服务端开发(动态网页技术)
HTTP:HTTP协议
定义
HTTP(HyperText Transfer Protocol,超文本传输协议)最早就是计算机与计算机之间沟通的一种标准协议,这种协议规范了通讯内容的格式以及各项内容的含义。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vsypxaNw-1618072022954)(/http-protocol.png)]
随着时代的发展,技术的变迁,这种协议现在广泛的应用在各种领域,也不仅仅局限于计算机与计算机之间,手机、电视等各种智能设备很多时候都在使用这种协议通讯,所以一般现在称 HTTP 为端与端之间的通讯协议。
Web 属于 B/S 架构的应用软件,在 B/S 架构中,浏览器与服务器沟通的协议就是 HTTP 协议,作为一个合格的 Web 开发者,了解 HTTP 协议中约定的内容是一门必修课。
应用软件架构一般分为两类:
- B/S 架构:Browser(浏览器) ←→ Server(服务器),这种软件都是通过浏览器访问一个网站使用,服务器提供数据存储等服务。
- C/S 架构:Client(客户端) ←→ Server(服务器),这种软件通过安装一个软件到电脑,然后使用,服务器提供数据存储等服务。
约定形式
- 客户端通过随机端口与服务端某个固定端口(一般为80)建立连接 三次握手
- 客户端向服务器发送一个连接请求
- 服务器向客户端返回一个确认信息
- 客户端将连接请求及这个确认信息发送服务器
- 客户端通过这个连接发送请求到服务端(这里的请求是名词)
- 服务端监听端口得到的客户端发送过来的请求
- 服务端通过连接响应给客户端状态和内容
要求:接下来的一个月,每次上网打开任何一个页面时都要能够脑补这个画面,默念这个流程。
约定内容-重点
- 请求 / 响应报文格式
- 请求方式 —— GET / POST / PUT / DELETE / OPTION…
- 响应状态 —— 200 / 404 / 302 / 304 …
- 预设的请求 / 响应头
核心概念
请求报文
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KO5J9djx-1618072022959)(/request.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VvF31I5F-1618072022961)(/request-structure.png)]
请求行
GET http://127.0.0.1:3000/getData HTTP/1.1
请求方式 + 空格 + 请求路径 + 空格 + HTTP 协议版本
请求头
客户端想要告诉服务端的一些额外信息,以下为常见的请求头(不用刻意去记忆):
键 | 值 |
---|---|
Host | 请求的主机 |
Cache-Control | 控制缓存(例如:max-age=60 缓存 60 秒) |
Accept | 客户端想要接收的文档类型,逗号分隔 |
User-Agent | 标识什么客户端帮你发送的这次请求 |
Referer | 这次请求的来源 |
Accept-Encoding | 可以接受的压缩编码 |
Cookie | 客户端本地的小票信息 |
请求体
这次请求客户端想要发送给服务端的数据正文,一般在 GET 请求时很少用到,因为 GET 请求主观上都是去“拿东西”。
响应报文
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kITDczs1-1618072022964)(/response.png)]
状态行
HTTP/1.1 200 OK
HTTP 协议版本 + 空格 + 状态码 + 空格 + 状态描述
响应头
服务端想要告诉客户端的一些额外信息,常见的有以下:
键 | 值 |
---|---|
Date | 响应时间 |
Server | 服务器信息 |
Content-Type | 响应体的内容类型 |
Content-Length | 响应的内容大小 |
Set-Cookie | 让客户端设置一个小票 |
响应体
这次请求服务端想要返回给客户端的数据正文,一般返回的都是 HTML,也可以返回数据, JavaScript 或者 CSS(需要修改响应头中的响应类型)。
补充:状态码
了解即可,不用刻意去记忆,用多了自然就忘不了。
http://www.w3school.com.cn/tags/html_ref_httpmessages.asp
状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。
- 1xx:指示信息 —— 表示请求已接收,继续处理。
- 2xx:成功 —— 表示请求已被成功接收、理解、接受。
- 3xx:重定向 —— 要完成请求必须进行更进一步的操作。
- 4xx:客户端错误 —— 请求有语法错误或请求无法实现。
- 5xx:服务器端错误 —— 服务器未能实现合法的请求。
常见状态代码、状态描述的说明如下。
- 200 OK:客户端请求成功。
- 400 Bad Request:客户端请求有语法错误,不能被服务器所理解,例如常见的参数传递错误。
- 401 Unauthorized:请求未经授权,这个状态代码必须和
WWW-Authenticate
报头域一起使用。 - 403 Forbidden:服务器收到请求,但是拒绝提供服务。
- 404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
- 500 Internal Server Error:服务器发生不可预期的错误。
- 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常
网络基础概念(了解)
IP 地址
Internet Protocol Address
设备在某一个网络中的地址,目前最常见的格式:[0-255].[0-255].[0-255].[0-255]
即为四个 0-255 的数字组成。本质是四组八位的二进制数。
作用就是标识一个网络设备(计算机、手机、电视)在某一个具体的网络当中的地址。
127.0.0.1 是本地回环地址 localhost:用来测试本机服务器是否连通
单个网络情况
在单个局域网下,结构非常简单,就是我们所连接的网络设备(网关)给我们分配了一个地址,在这个范围之内我们都可以通过这个地址找到我们的这个设备。
如果设备没有连接任何网络情况下,我们会有一个本地回环地址 127.0.0.1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uBxJi8CC-1618072022966)(/single-network.png)]
多个网络情况
但是当一个设备同时处于多个网络下(比如同时连接了有线网卡和无线网卡),就会变得稍微复杂一点:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9LpUALlC-1618072022966)(/multiple-network.png)]
域名
由于 IP 地址都是没有规律的一些数字组成的,很难被人记住,不利于广泛传播,所以就有人想出来要给 IP 起名字(别名)。
特殊的域名
localhost
含义为本地主机,对应127.0.0.1 。这是一个保留域名,主要用于本地测试。
DNS(这里仅需要了解)domain name system
通过宽带运营商提供的服务器解析一个域名背后对应的 IP,这个过程叫做 DNS 寻址,帮你完成 DNS 寻址过程的服务器叫做 DNS 服务器。
hosts 文件
操作系统在发起对 DNS 服务器的查询请求之前,会优先检查本机的 hosts 文件。如果这个文件中包含了对当前需要解析的域名的配置,则不再发起对 DNS 服务器的请求,直接使用 hosts 文件中的配置。
文件所在路径:
- Windows:
C:\Windows\System32\drivers\etc\hosts
- macOS:
/etc/hosts
注意:
- 本机的 hosts 文件配置只能到影响本机的 DNS 寻址
- 只有以管理员权限运行的编辑器才有权利修改
hosts
文件
端口
计算机本身是一个封闭的环境,就像是一个大楼,如果需要有数据通信往来,必须有门,这个门在术语中就叫端口,每一个端口都有一个编号,每台计算机只有 65536 个端口(0-65535)。
可以通过在命令行中运行: netstat -an
命令监视本机端口使用情况:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G7QAI2hj-1618072022969)(/netstat.png)]
参考链接:
- https://baike.baidu.com/item/%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E5%8F%A3
- https://baike.baidu.com/item/%E7%AB%AF%E5%8F%A3
http
默认的端口80
https
默认的端口是443
URL
URL(Uniform Resource Locator),统一资源定位符,通俗点来说就是表示网络当中某一个网页的完整访问地址,它具有一定的格式:
– 协议名称://域名:端口/文件目录(文件名称)?key=value&key2=value2
例如:https://itcast.cn:80/schools/students?id=18&name=zce
总结请求响应流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QoSNLBIH-1618072022970)(/http-req-res.png)]
- 用户打开浏览器
- 地址栏输入我们需要访问的网站网址(
URL
) - 浏览器通过
DNS 服务器
获取即将访问的网站IP 地址
- 浏览器发起一个对这个 IP地址的 (
请求
) - 服务端监听指定的
端口
的服务器软件接收到这个请求,进行相应的处理(处理
) - 服务端将处理完的结果返回给客户端浏览器(
响应
) - 浏览器接收服务端返回的结果并相应相应的处理(
渲染
)
GET与POST
GET请求
请求在网站的访问过程中很常见,并且请求分为多种方式:GET、POST、PUT、DELETE、OPTIONS等。其中GET和POST最常用。
什么是GET请求?
GET从字面上理解为’获取’,通常用于获取服务端的数据。
常见的发起GET请求的方式
- 地址栏访问
- src/href
- 表单:method=‘get’
- ajax:type设置为get
网页中有许多效果使用的就是GET请求:
- 各种搜索框
- 各种详情页面
- 大部分超链接
GET方式提交数据的格式
- 格式:index.php?userName=jack&password=123
- 参数名与参数值之间没有空格
- 参数值不需要使用单双引号包括
GET方式提交数据的特点:
- get方式在url后面拼接参数,只能以文本的形式传递数据
- 传递的数据量小,4KB左右(不同浏览器会有差异)
- 安全性低,会将数据显示在地址栏
- 速度快,通常用于对安全性要求不高的请求
POST请求
什么是post请求
字面上理解,post就是指发送,提交
,它可以向指定的资源提交要被处理的数据
为什么需要POST请求
GET方式提交数据通过URL传递到请求的页面,提交的数据量一般较小,用于请求页面数据。此外,GET方式传递的数据安全性低, 对于密码等隐私信息、文件上传必须使用POST方式提交。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6AbVon7F-1618072022971)(post%E8%AF%B7%E6%B1%82%E7%A4%BA%E4%BE%8B.png)]
要求:如果使用表单方式进行提交,表单的method必须设置为POST。
特点
1-post 方式 安全性比较高
2-传递数据量大,请求对数据长度没有要求
3-请求不会被缓存,也不会保留在浏览器历史记录中
用于:密码等安全性要求比较高的场合,提交的数据量比较大:发布文章,上传文件。
传统请求方式所带来的问题
案例:实现用户注册,有一个需求,用户名必须是唯一的,我们如何知道用户是否是唯一,我们就需要调用指定的能够验证用户名是否唯一
的接口,传入当前用户输入的自定义数据,进行验证,获取验证的返回结果,如果重复则给出用户提示,如果不重复,不用处理
-
什么时候发送验证请求:失去焦点的时候就发送验证请求
-
找到后台接口
-
实现代码:
document.querySelector(".username").onblur = function(){ var username = this.value location.href='http://127.0.0.1:3002/validataUserName?name='+username }
-
这种实现方式的问题
- 页面会进行跳转,当页面跳转回来的时候,之前输入的数据有可能已经清空,不利于用户体验
- 当前方式的验证会阻塞用户的下一步操作
-
我们的需要:
- 页面不要跳转,页面也不要整体刷新
- 验证操作不能阻塞用户的下一步操作
AJAX编程
Ajax的概念
即 Asynchronous Javascript And XML,AJAX 不是一门的新的语言,而是对现有持术的综合利用。
- 基于web标签的xhtml+css
- 可以使用dom进行动态的显示和交互
- 使用XML和XSLT(是一种用于将XML转换为任意文本的描述语言)进行数据的交换和操作
- 使用XMLHttpRequest进行异步的数据查询和检索等操作。。。
本质:是在HTTP协议的基础上以异步的方式通过XMLHttpRequest对象与服务器进行通信。
作用:可以在页面不刷新的情况下,请求服务器,局部更新页面的数据;
异步(Asynchronous [eɪˈsɪŋkrənəs])
指某段程序执行时不会阻塞其它程序执行,其表现形式为程序的执行顺序不依赖程序本身的书写顺序,相反则为同步。
其优势在于不阻塞程序的执行,从而提升整体执行效率。
同步:同一时刻只能做一件事,上一步完成才能开始下一步
异步:同时做多件事,效率更高
XMLHttpRequest可以以异步方式的处理程序。
XMLHttpRequest
浏览器内建对象,用于在后台与服务器通信(交换数据) ,由此我们便可实现对网页的部分更新,而不是刷新整个页面。
下面是一个简单的例子(获取验证码)
// 这只是一个示例,不用考虑他所实现的功能
var xhr = new XMLHttpRequest()
xhr.open('post','http://127.0.0.1:3002/getcode')
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
xhr.send('phone=13176849023')
xhr.onload = function () {
console.log(this.response);
}
由于XMLHttpRequest本质基于HTTP协议实现通信,所以结合HTTP协议和上面的例子我们分析得出如下结果:
请求
HTTP请求3个组成部分与XMLHttpRequest方法的对应关系
1、请求行
xhr.open('post','http://127.0.0.1:3002/getcode')
post方式的请求不用在url中拼接 参数
2、请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
**get 请求可以不设置 **
3、请求主体
xhr.send('phone=13176849023')
get的参数在url中拼接 ,所以send里面可以传入null或者不传
响应
HTTP响应是由服务端发出的,作为客户端更应关心的是响应的结果。
由于服务器做出响应需要时间(比如网速慢等原因),所以我们需要监听服务器响应的状态,然后才能进行处理。
// 当服务器响应之后,会自动的触发onload事件,在这个事件里面我们可以获取服务器所返回的所有详细数据,然后根据自己的需要进行处理
xhr.onload = function () {
console.log(this.response);
}
使用异步对象实现验证用户名是否重复
document.querySelector(".username").onblur = function () {
var username = this.value
var xhr = new XMLHttpRequest()
// - 让异步对象发送请求
xhr.open('get', 'http://127.0.0.1:3002/validateusername?name='+username)
xhr.send(null)
// - 让异步对象获取响应结果
// onreadystatechange:监听当前异步对象的操作状态
xhr.onload = function(){
var result = JSON.parse(this.response)
if(result.code == 401){
document.querySelector('.msg').innerHTML = result.msg
document.querySelector(".username").focus()
}
else{
document.querySelector('.msg').innerHTML = result.msg
}
}
}
get方式请求示例
需求:获取所有用户数据,并实现简易的动态渲染(第一个动态页面哦)
接口:http://127.0.0.1:3002/getUserList
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
table {
width: 500px;
border: 1px solid #666;
margin: 100px auto;
border-collapse: collapse;
}
th,
td{
height: 50px;
border:1px solid #666;
}
</style>
</head>
<body>
<button class="btn">点我获取数据</button>
<table>
<thead>
<tr>
<th>用户名</th>
<th>密码</th>
<th>手机号码</th>
</tr>
</thead>
<tbody>
<tr>
<td>固定用户名</td>
<td>固定密码</td>
<td>固定手机号</td>
</tr>
</tbody>
</table>
<script>
document.querySelector('.btn').onclick = function(){
// 1.创建异步对象
let xhr = new XMLHttpRequest()
// 2.设置请求行
xhr.open('get','http://127.0.0.1:3002/getUserList')
// 3.不用设置请求头
// 4.设置请求体
xhr.send(null)
// 5.添加监听
xhr.onload = function(){
// console.log(JSON.parse(xhr.response))
// 5.1 获取返回数据,并进行类型的转换
let res = JSON.parse(xhr.response)
console.log(res.data)
// 5.2 循环生成动态结构
let html = ''
res.data.forEach(function(value){
html += '<tr>'
html += `<td>${value.username}</td>`
html += `<td>${value.password}</td>`
html += `<td>${value.phone}</td>`
html += '</tr>'
})
// 5.3 将生成的动态结构渲染到页面指定的位置
document.querySelector('tbody').innerHTML = html
}
}
</script>
</body>
</html>
post方式请求示例
需求:实现登陆的注册,接口:http://127.0.0.1:3002/addUser
1.使用XMLHttpRequest发送异步请求
2.添加onload监听,接收返回数据并给出用户提示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="">
用户名:<input type="text" name='username' class="uname"> <br>
密码:<input type="text" name="password" class="upass"> <br>
手机号码:<input type="text" name="phone" class="uphone"> <br>
<input type="button" value="注册" class="btn">
</form>
<script>
document.querySelector('.btn').onclick = function(){
// 0 获取用户数据
var name = document.querySelector('.uname').value
var pass = document.querySelector('.upass').value
var phone = document.querySelector('.uphone').value
// 1.创建异步对象
var xhr = new XMLHttpRequest()
// 2.发送请求
// 2.1 设置请求行
// post方式的参数不是在url中拼接的
xhr.open('post','http://127.0.0.1:3002/addUser')
// 2.2 设置请求头
// post方式如果有参数fdsv设置请求头Content-Type,否则参数不能正确的传递
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
// 2.3 设置请求体
// get方式没有请求体,它是传递null
// 但是post方式如果有参数就需要在请求体中传递,参数格式为key=value&key=value
xhr.send('username='+name+'&password='+pass+'&phone='+phone)
// 3.接收响应
// 3.1 添加监听
// 3.2 进行成功请求的判断:
// 3.3 获取返回数据:responseText
xhr.onload = function(){
if(xhr.status == 200){
// responseText是字符串,所以转换为js对象,方便我们的使用
var result = JSON.parse(xhr.responseText)
alert(result.msg)
}
}
}
</script>
</body>
</html>
AJAX 补充
onreadystatechange
- onload 是 HTML5 以后新增的方便获取响应的事件
- 过去获取浏览器返回内容的时候使用的是 onreadystatechange
在通过Ajax向服务器发送请求的过程中,XMLHttpRequest
对象的状态会发生多次变化。由于 readystatechange
事件是在 xhr
对象状态变化时触发(不单是在得到响应时),也就意味着这个事件会被触发多次
onreadystatechange 是 Javascript 的事件的一种,其意义在于监听 XMLHttpRequest 的状态
...发送请求...
// 接收响应
xhr.onreadystatechange = function () {
console.log('事件被触发了')
}
常见属性和方法
1、获取状态行(包括状态码&状态信息)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tEri4nV-1618072022972)(/06-responseLine.png)]
2、获取响应头
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mc3g0QWh-1618072022974)(/07-responseHead.png)]
3、响应主体
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6WNzPUS-1618072022975)(/08-responseBody.png)]
我们需要检测并判断响应头的MIME类型后确定使用request.responseText或者request.responseXML
API 详解
xhr.open() 发起请求,可以是get、post方式
xhr.setRequestHeader() 设置请求头
xhr.send() 发送请求主体get方式使用xhr.send(null)
xhr.onreadystatechange = function () {} 监听响应状态
readstate 属性有五个状态:
- xhr.readyState = 0时,(未初始化)还没有调用send()方法
- xhr.readyState = 1时,(载入)已调用send()方法,正在发送请求
- xhr.readyState = 2时,(载入完成)send()方法执行完成,已经接收到全部响应内容
- xhr.readyState = 3时,(交互)正在解析响应内容
- xhr.readyState = 4时,(完成)响应内容解析完成,可以在客户端调用了
不用记忆状态,只需要了解有状态变化这个概念
xhr.status表示响应码,如200
xhr.statusText表示响应信息,如OK
xhr.getAllResponseHeaders() 获取全部响应头信息
xhr.getResponseHeader(‘key’) 获取指定头信息
xhr.responseText、xhr.responseXML都表示响应主体
注:GET和POST请求方式的差异(面试题)
1、GET没有请求主体,使用xhr.send(null)
2、GET可以通过在请求URL上添加请求参数
3、POST可以通过xhr.send(‘name=itcast&age=10’)
4、POST需要设置
Content-Type:application/x-www-form-urlencoded
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ANWKo1HK-1618072022976)(/09-post-request-head.png)]
5、GET大小限制约4K,POST则没有限制
一个简单的案例
动态渲染用户列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
table {
width: 500px;
border: 1px solid #666;
margin: 100px auto;
border-collapse: collapse;
}
th,
td {
height: 50px;
border: 1px solid #666;
}
</style>
</head>
<body>
<button class="btn">点我获取数据</button>
<table>
<thead>
<tr>
<th>用户名</th>
<th>密码</th>
<th>手机号码</th>
</tr>
</thead>
<tbody>
<tr>
<td>固定用户名</td>
<td>固定密码</td>
<td>固定手机号</td>
</tr>
</tbody>
</table>
<script>
document.querySelector('button').onclick = function () {
// 创建异步对象读取数据
var xhr = new XMLHttpRequest()
xhr.open('get', 'http://127.0.0.1:3002/getUserList')
xhr.send(null)
// 监听异步对象的状态
xhr.onreadystatechange = function () {
// 如果服务器成功响应,且数据解析完毕可以使用了,则进行返回数据的处理
if (xhr.status == 200 && xhr.readyState == 4) {
// 返回数据是字符串,所以需要进行类型的转换
let res = JSON.parse(xhr.response)
// 循环生成动态结构
let html = ''
res.data.forEach(function (value) {
html += '<tr>'
html += `<td>${value.username}</td>`
html += `<td>${value.password}</td>`
html += `<td>${value.phone}</td>`
html += '</tr>'
})
// 将生成的动态结构渲染到页面指定的位置
document.querySelector('tbody').innerHTML = html
}
}
}
</script>
</body>
</html>
XML(了解)
XML是一种标记语言,很类似HTML,其宗旨是用来传输数据,具有自我描述性(固定的格式的数据)。
<?xml version='1.0' encoding='utf-8'?>
<root>
<items>
<item>
<img>/images/0.jpg</img>
<name>张三</name>
</item>
<item>
<img>/images/1.jpg</img>
<name>李四</name>
</item>
<item>
<img>/images/2.jpg</img>
<name>王五</name>
</item>
<item>
<img>/images/3.jpg</img>
<name>赵六</name>
</item>
</items>
</root>
语法规则
1、必须有一个根元素
2、标签名称不可有空格、不可以数字或.开头、大小写敏感
3、不可交叉嵌套
4、属性双引号(浏览器自动修正成双引号了)
5、特殊符号要使用实体
6、注释和HTML一样
虽然可以描述和传输复杂数据,但是其解析过于复杂并且体积较大,所以实现开发已经很少使用了。
一个简单的示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
table {
width: 800px;
/* 可以让表格的默认的双层边框成为单层边框 */
border-collapse: collapse;
margin: 0 auto;
}
td {
text-align: center;
}
td img {
width: 50px;
}
</style>
</head>
<body>
<table border="1">
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>头像</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
window.onload = function () {
var xhr = new XMLHttpRequest()
xhr.open('post', 'http://127.0.0.1:3002/getxml')
xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded")
xhr.send(null)
xhr.onload = function () {
if (xhr.status == 200) {
// 获取结果,由于数据是xml格式,所以通过responseXML来获取数据
// 它获取到的数据的本质是document,所以可以相像,xml文档的解析方式和之前的dom是类似一样的
console.log(xhr.responseXML)
console.log(typeof xhr.responseXML) // object
// 下面这个东东是document,意味着之前如何操作html文档,现在也如何操作xml文档
var result = xhr.responseXML
// 1.获取所有item
var allItem = result.querySelectorAll('item')
console.log(allItem)
// 遍历数组
var html = ''
for (var i = 0; i < allItem.length; i++) {
var img = allItem[i].querySelector('img').innerHTML
var name = allItem[i].querySelector('name').innerHTML
// 这里使用到了ES6的模板字符串:``
html += `<tr>
<td>${i + 1}</td>
<td>${name}</td>
<td><img src="http://127.0.0.1:3002${img}" alt=""></td>
<td>
<a href="javascript:;">查看</a>
<a href="javascript:;">修改</a>
<a href="javascript:;">删除</a>
</td>
</tr>`
}
document.querySelector('tbody').innerHTML = html
}
}
}
</script>
</body>
</html>
JSON(重点掌握)
即 JavaScript Object Notation,另一种轻量级的文本数据交换格式,独立于语言。
1.它是用来描述数据的
2.它是字符串
3.永远不要在json文件中添加注释
4.键和值都需要使用双引号,除非这个值是数值或bool值
语法规则
1、数据在名称/值对中
2、数据由逗号分隔(最后一个健/值对不能带逗号)
3、花括号保存对象方括号保存数组
4、键和值都使用双引号包含,除非值是数值或者bool类型
JSON()解析
JSON数据在不同语言进行传输时,类型为字符串,不同的语言各自也都对应有解析方法,需要解析完成后才能读取,下面是在js中的解析方法:
1、JSON.parse(json字符串):将json字符串转换为js对象
2、JSON.stringify(js数组或对象):将js对象转换为json格式字符串
总结:JSON体积小、解析方便且高效,在实际开发成为首选。
封装AJAX工具函数
前言:之前每次发判断请求,如果请求方式,或者参数或者url不一样,那么代码无法复用,所以我们迫切的需要一个通用函数,让用户在使用异步对象的时候通过调用一个相同的函数就可以实现需求
总之:为了提升我们的开发效率,我们自已将XMLHttpRequest封装成一个函数。
思路分析
-
封装函数的关键在于
-
找到操作的共同点
-
找到不同的部分–以后就是参数
-
观察我们的异步操作那些不一样?
-
请求方式:type
-
请求url:url
-
请求参数不一样:data
-
数据的转换方式–返回数据的格式:dataType
-
对于数据的处理方式不一样:success:这是一个函数
-
函数的封装形式:
var $ = { ajax:function(option){ // 实现具体的业务处理 } }
-
success:是一个回调函数
-
-
代码实现
var $ = {
ajax:function(option){
// 实现具体的业务处理
var xhr = new XMLHttpRequest()
// 接收参数
var type= option.type || 'get'
// location.pathname:当前页面的全路径
var url = option.url || location.pathname
var data = option.data || ''
var dataType = option.dataType || 'text/html'
var success = option.success
// 发送请求
// 设置请求行:get如果有参数就需要拼接在url后面,post不用拼接
if(type == 'get'){
url = url + "?" + data
data = null
}
xhr.open(type,url)
// 设置请求头:get方式不需要设置请求头,post方式需要设置Content-Type
if(type == 'post'){
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
}
// 设置请求体:如果有参数,post方式在请求体中传递参数
xhr.send(data)
// 接收响应
xhr.onload = function(){
// 调用回调
success && success(this.response)
}
}
}
测试自己封装的工具函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入自己封装的ajax -->
<script src="./js/myajax.js"></script>
</head>
<body>
<button class="getbtn">测试get</button>
<hr>
<form action="">
用户名:<input type="text" name='username' class="uname"> <br>
密码:<input type="text" name="password" class="upass"> <br>
手机号码:<input type="text" name="phone" class="uphone"> <br>
<button class="postbtn">测试post</button>
</form>
<script>
// 获取所有用户数据--测试get方式
document.querySelector('.getbtn').onclick = function(){
$.ajax({
type:'get',
url:'http://127.0.0.1:3002/getUserList',
dataType:'json',
// 回调函数
success:function(res){
// 下面是调用者确定的数据处理逻辑
console.log(res)
}
})
}
// 用户注册--测试post方式
document.querySelector('.postbtn').onclick = function(){
var name = document.querySelector('.uname').value
var pass = document.querySelector('.upass').value
var phone = document.querySelector('.uphone').value
$.ajax({
type:'post',
url:'http://127.0.0.1:3002/addUser',
dataType:'json',
data:`username=${name}&password=${pass}&phone=${phone}`,
// 回调函数
success:function(res){
// 下面是调用者确定的数据处理逻辑
console.log(res)
}
})
}
</script>
</body>
</html>
jQuery中的Ajax
基本介绍
jQuery为我们提供了更强大的Ajax封装
$.ajax({}) 可配置方式发起Ajax请求
- url 接口地址 *
- type 请求方式 *
- timeout 请求超时 *
- dataType 服务器返回格式 *
- data 发送请求数据 *
- beforeSend:function () {} 请求发起前调用 *
- success 成功响应后调用 *
- error 错误响应时调用 *
- complete 响应完成时调用(包括成功和失败) *
$.get(url,data,callback,dataType) 以GET方式发起Ajax请求
$.post(url,data,callback,dataType) 以POST方式发起Ajax请求
$(‘form’).serialize()序列化表单(即格式化key=val&key=val)
jQuery Ajax介绍
http://www.w3school.com.cn/jquery/jquery_ref_ajax.asp
一个应用示例:用户注册
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="" id='myform'>
用户名:<input type="text" name='username' class="uname"> <br>
密码:<input type="text" name="password" class="userpass"> <br>
手机号:<input type="text" name="phone" class="userPhone"> <br>
<input type="button" value="注册" class="btn">
</form>
<!-- 引入jq -->
<script src="./js/jquery.min.js"></script>
<script>
$('.btn').on('click', function () {
// 使用jq中封装的ajax
$.ajax({
type: 'post',
url: 'http://127.0.0.1:3002/addUser',
// serialize:可以将表单元素序列化为key=value&key=value的格式
// 必须注意的是:想使用serialize()获取参数,必须为表单元素设置name属性,这个name属性以后会成为参数的key,如果没有设置name属性,则无法生成相应的key,意味着参数无法正确的获取
data: $('#myform').serialize(),
dataType: 'json',
// 如果响应超出1秒,那么就认为是请求失败,如果失败error函数可以进行错误处理
timeout:6000,
// 这个函数有一个参数,这个参数就是当前的错误信息对象
error:function(err){
console.log(err)
},
// 发送请求之前的回调函数,这个函数一般会进行请求之前的操作,如验证
beforeSend:function(){
// 验证用户名是否有输入且不能包含特殊符号
// \w:0-1 a-z A-Z _
var regname = /\W/
var uname = document.querySelector('.uname').value
// 如果没有输入 或者 输入的内容包含特殊符号
if(uname.trim().length ==0 || regname.test(uname)){
alert('用户名输入不正确')
// return false可以中止本次请求,如果想中止本次请求,必须返回return false
return false
}
// 验证密码的长度是否>=6位,如果小于6位,则给出提示信息
if(document.querySelector('.userpass').value.length< 6){
alert('密码输入不正确')
return false
}
// 验证手机号是否格式正确
var regPhone = /^1[35789]\d{9}$/
if(!regPhone.test(document.querySelector('.userPhone').value)){
alert('手机号输入不正确')
return false
}
},
success: function (res) {
// 自己决定处理方式
console.log(res)
if(res.code == 200){
alert('注册成功')
}else{
alert('注册失败')
}
},
// 请求完成时的回调,不管成功还是失败都会调用
complete:function(){
console.log('无论请求成功还是失败都会执行的代码')
}
})
})
</script>
</body>
</html>
模板引擎
Js插件 template_native.js template.js
作用:渲染数据时 代替 拼接字符串的操作
其它流行模板引擎
BaiduTemplate:http://tangram.baidu.com/BaiduTemplate/
ArtTemplate:http://aui.github.io/art-template/zh-cn/
velocity.js:https://github.com/shepherdwind/velocity.js/
Handlebars:http://handlebarsjs.com/
http://blog.jobbole.com/56689/
art-Template
简介:artTemplate 是新一代 javascript 模板引擎,它采用预编译方式让性能有了质的飞跃,并且充分利用 javascript 引擎特性,使得其性能无论在前端还是后端都有极其出色的表现。
artTemplate 原生 js 模板语法
-
引入插件
<script src="template-web.js"></script>
-
逻辑表达式
<% 与 %> 符号包裹起来的语句则为模板的逻辑表达式
-
输出表达式 (编码可以防止数据中含有 HTML 字符串,避免引起 XSS 攻击)
- 对内容编码输出:<%=content%>
- 不编码输出:<%=##content%>
-
示例:
<script type="text/template" id='temp'> <h1><%=value%></h1> <ul> <%for(i = 0; i < arr.length; i ++) {%> <li>数组元素的内容 <%=i + 1%> :<%=arr[i]%></li> <%}%> </ul> </script>
5.核心方法
template(模板id,数据对象):返回动态生成的页面结构
6.案例:使用模板引擎原生语法渲染首页
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hero - Admin</title>
<link rel="stylesheet" href="./css/bootstrap.css">
<style>
.hero-list img {
width: 50px;
height: 50px;
display: block
}
.hero-list td {
height: 50px;
line-height: 50px;
}
</style>
</head>
<body>
<header>
<div class="page-header container">
<h1>王者荣耀 <small>英雄管理器</small></h1>
</div>
</header>
<div class="container hero-list">
<table class="table table-hover">
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>性别</th>
<th>头像</th>
<th>操作</th>
</tr>
</thead>
<tbody id="tbody">
<tr>
<td>1</td>
<td>jack</td>
<td>男</td>
<td><img src="http://127.0.0.1:3002/images/1.jpg"></td>
<td><a href="#">查看</a> <a href="javascript:;">修改</a>
<a href="javascript:;">删除</a></td>
</tr>
</tbody>
</table>
</div>
<!-- 下面创建页面动态结构所需要的模板 -->
<!--type属性就是规范了里面的代码以何种语法进行解析 ,script默认的type为text/javascript,script有默认的type,如果设置类型为text/template,那么浏览器知道这不是js,也不会按js语法进行解析,同时它还知道这是一个模板结构,所以会按模板结构的语法处理 -->
<script type="text/template" id='listTemp'>
<% for(var i=0; i < data.length; i++){%>
<tr>
<td><%=i+1%></td>
<td><%=data[i].name%></td>
<td><%=data[i].gender%></td>
<td><img src="http://127.0.0.1:3002/images/<%=data[i].img%>"></td>
<td><a href="#">查看</a> <a href="/edit?id=1">修改</a>
<a href="/delete?id=1">删除</a></td>
</tr>
<%} %>
</script>
<!-- 引入jq -->
<script src="./js/jquery.min.js"></script>
<!-- 引入模板引擎 -->
<script src="./js/template-web.js"></script>
<script>
$(function () {
// 页面一加载就发起ajax请求
$.ajax({
type: 'get',
url: 'http://127.0.0.1:3002/getalldata',
dataType: 'json',
success: function (result) {
console.log(result)
if (result.code == 200) {
// 调用模板引擎,生成动态结构
var html = template('listTemp', result)
// 将动态结构填充到页面指定结构
$('#tbody').html(html)
}
}
})
})
</script>
</body>
</html>
artTemplate 简洁语法
-
引入插件
<script src="template-web.js"></script
-
逻辑表达式:
{{
与}}
符号包裹起来的语句则为模板的逻辑表达式 -
输出表达式:(编码可以防止数据中含有 HTML 字符串,避免引起 XSS 攻击)
- 对内容编码输出:{{content}}
- 不编码输出:{{##content}}
-
条件表达式:
{{if 条件}} <p>内容</p> {{else if value > 0}} <p>内容</p> {{else}} <p>内容!</p> {{/if}}
-
循环遍历表达式:无论数组或者对象都可以用 each 进行遍历
{{each list as value index}} <li>{{index}} - {{value.user}}</li> {{/each}} // 也可以简写为: {{each list}} <li>{{$index}} - {{$value.user}}</li> {{/each}}
6.核心方法
template(模板id,数据对象):返回动态生成的页面结构
7.案例:使用模板引擎简写语法渲染首页
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hero - Admin</title>
<link rel="stylesheet" href="./css/bootstrap.css">
<style>
.hero-list img {
width: 50px;
height: 50px;
display: block
}
.hero-list td {
height: 50px;
line-height: 50px;
}
</style>
</head>
<body>
<header>
<div class="page-header container">
<h1>王者荣耀 <small>英雄管理器</small></h1>
</div>
</header>
<div class="container hero-list">
<table class="table table-hover">
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>性别</th>
<th>头像</th>
<th>操作</th>
</tr>
</thead>
<tbody id="tbody">
<tr>
<td>1</td>
<td>jack</td>
<td>男</td>
<td><img src="http://127.0.0.1:3002/images/1.jpg"></td>
<td><a href="#">查看</a> <a href="javascript:;">修改</a>
<a href="javascript:;">删除</a></td>
</tr>
</tbody>
</table>
</div>
<!-- 下面创建页面动态结构所需要的模板 -->
<!--type属性就是规范了里面的代码以何种语法进行解析 ,script默认的type为text/javascript,script有默认的type,如果设置类型为text/template,那么浏览器知道这不是js,也不会按js语法进行解析,同时它还知道这是一个模板结构,所以会按模板结构的语法处理 -->
<script type="text/template" id='listTemp'>
{{each data as value index}}
<tr>
<td>{{i+1}}</td>
<td>{{value.name}}</td>
<td>{{value.gender}}</td>
<td><img src="http://127.0.0.1:3002/images/{{value.img}}"></td>
<td><a href="#">查看</a> <a href="javascript:;">修改</a>
<a href="javascript:;">删除</a></td>
</tr>
{{/each}}
</script>
<!-- 引入jq -->
<script src="./js/jquery.min.js"></script>
<!-- 引入模板引擎 -->
<script src="./js/template-web.js"></script>
<script>
$(function () {
// 页面一加载就发起ajax请求
$.ajax({
type: 'get',
url: 'http://127.0.0.1:3002/getalldata',
dataType: 'json',
success: function (result) {
console.log(result)
if (result.code == 200) {
// 调用模板引擎,生成动态结构
var html = template('listTemp', result)
// 将动态结构填充到页面指定结构
$('#tbody').html(html)
}
}
})
})
</script>
</body>
</html>
XMLHttpRequest2.0
技术总是在实践中不断更新的,XMLHttpRequest也不例外。
4.1 设置超时
a) 设置超时 xhr.timeout
b) 监听超时事件 xhr.ontimeout = function () {// code}
当请求超时,此事件就会被触发
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vDbzjNZe-1618072022976)(/12-timeOut.png)]
4.2 FormData
a) 提供了一个新的内建对象,可用于管理表单数据
b) 首先要获取一个表单元素form
c) 然后在实例化时 new FormData(form),将表单元素form传进去
d) 会返回一个对象,此对象可以直接做为xhr.send(formData)的参数
e) 此时我们的数据就是以二进制形式传递了
f) 注意我们这里只能以post形式传递,浏览器会自动为我们设置一个合适的请求头
4.3 文件上传数据获取
a) 我们上传文件是以二进制形式传递的
b) 我们可以通过表单获取到一个文件对象
c) 然后file.files[0]可以获取文件信息
d) 然后再利用var formData = new FormData() 实例化
e) 然后再利用formData.append(‘upload’, file.files[0])将文件转成二进制
f) 最后将 formData 做为xhr.send(formData)的参数
4.4 上传进度
a) 利用XMLHttpRequest我们可以实现文件的上传
b) 并且我们可以通过xhr.upload.onprogress = function (ev) {// code},监听上传的进度
c) 这时我们上传的进度信息会保存在事件对象ev里
d) ev.loaded 表示已上传的大小,ev.total表示文件整体的大小
e) var percent = ev.loaded / ev.total