通过Axios工具认识AJAX
通过Axios工具认识AJAX
以下为学习过程中的极简提炼笔记,以供重温巩固学习
学习准备
准备工作
学习目的
之前所学的技术,只能把网页做的更美观漂亮,或添加一些动画效果
Ajax能让我们轻松实现网页与服务器之间的数据交互
背景知识
服务器与客户端
服务器:负责存放和对外提供资源
客户端:负责获取和消费资源
URL构成
URL(全称是UniformResourceLocator)统一资源定位符,用于标识互联网上每个资源的唯一存放位置
浏览器只有通过URL地址,才能正确定位资源的存放位置,从而成功访问到对应的资源
URL地址一般由三部组成: ① 客户端与服务器之间的通信协议 http:// ② 存有该资源的服务器名称 www.xxxx.com ③ 资源在服务器上具体的存放位置 /sss/ssss/sssss.html
URL的组成:协议://域名/资源路径
协议:规定了浏览器和服务器之间传输数据的格式 域名:指出访问的是哪一台服务器电脑,标记服务器在互联网中方位 资源路径:标识访问文件在服务器电脑当中的具体位置
URL查询参数
定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据
语法:http://xxx.com/xxx/xxx?参数名1=值1&参数名2=值2......
在axios中的查询方式见axios查询参数
通信过程
客户端与服务器之间的通信过程,分为 请求 – 处理 – 响应 三个步骤
网页中的每一个资源,都是通过 请求 – 处理 – 响应 的方式从服务器获取回来的
- HTML是网页的骨架
- CSS是网页的颜值
- Javascript是网页的行为
- 数据,则是网页的灵魂
骨架、颜值、行为皆为数据服务,数据在网页中无处不在
网页请求通信
如果要在网页中请求服务器上的数据资源,则需要用到 XMLHttpRequest 对象
XMLHttpRequest(简称 xhr)是浏览器提供的 js 成员
网页通过XMLHttpRequest,可以请求服务器上的数据资源
最简单的用法 var xhrObj = new XMLHttpRequest()
客户端请求服务器通信
客户端请求服务器时,请求的方式有很多种
最常见的两种请求方式分别为 get 和 post 请求
- get 请求通常用于获取服务端资源(向服务器要资源)
例如:根据 URL 地址,从服务器获取 HTML 文件、css 文件、js文件、图片文件、数据资源等
- post 请求通常用于向服务器提交数据(往服务器发送资源)
例如:登录时向服务器提交的登录信息、注册时向服务器提交的注册信息、添加用户时向服务器提交的用户信息等各种数据提交操作
AJAX概念
AJAX 的全称是 Asynchronous Javascript And XML(异步 JavaScript 和 XML)
AJAX 是浏览器与服务器之间的一种异步通信方式
通俗的理解:在网页中利用 XMLHttpRequest 对象和服务器进行数据交互的方式,就是Ajax
异步的JavaScript
它可以异步地向服务器发送请求,在等待响应的过程中,不会阻塞当前页面,在这种情况下,浏览器可以做自己的事情,直到成功获取响应后,浏览器才开始处理响应数据
XML
是前后端数据通信时传输数据的一种格式,现在已经不怎么用了,现在比较常用的是 JSON
所以归纳上述的概念,Ajax就是在浏览器不重新加载网页的情况下,对页面的某部分进行更新
如何使用并掌握AJAX
先使用axios库,与服务器进行数据通信
- 基于XMLHttpRequest封装、代码简单、下载量14亿
- Vue、React项目中都会使用到axios
再学习XMLHttpRequest对象的使用,了解AJAX底层原理
通过使用axios工具来认识AJAX
Axios 是一个基于 promise 的网络请求库,可以用于浏览器和 node.js
axios引入方法
- 方法一:CDN引用,引入axios.js https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js
将作为第三方axios库的相关代码,引入到自己的网页中
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
- 方法二:使用Npm
npm install axios
- 方法三:下载axios.js本地文件Github官网下载axios.js
然后找到 axios/dist/axios.min.js
使用axios函数及.then
获取方法
完成全局的axios库引入后,使用 axios 函数来调用
axios 函数的使用包括:
- 传入配置对象
- 再用
.then
回调函数接收结果,并做后续处理
<body>
<script>
axios({
url:'目标资源地址'
//固定名字的url属性,作用在于告诉axios去哪个服务器目标资源地址交互
//例 https://hmajax.itheima.net/api/province
})
.then((result) => {
//then方法 + result回调函数
//对服务器返回的数据做后续处理
})
</script>
</body>
语法格式案例 使用axios函数
<body>
<!-- 建立一个类名叫6的p标签 -->
<p class='6'></p>
<!-- 1. 引入axios库 -->
<script src='https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js'></script>
<!-- 2. 在网页JavaScript中使用axios函数 -->
<script>
axios({
url:'https://hmajax.itheima.net/api/province'
})
//.then的方法,定一个叫result回调函数(形参result)
.then((result) => {
//打印result回调函数,通过浏览器调试,确认打印结果,确认从url返回的是个对象结构
console.log(result)
//从返回对象中解构数据;好习惯,多利用浏览器调试打印,获取准确属性名
console.log(result.data.list)
//数组转字符串+指定拼接符,使用数组join方法
console.log(result.data.list.join(`<br>`))
//建立一个P标签,获取过来,把解构的结果,给P标签
document.querySelector('.6').innerHTML = result.data.list.join(`<br>`)
})
</script>
</body>
axios的查询参数params
axios中使用固定名字的params
选项,来查询参数名对应的键值
比起直接在url后面串接串拼,独立选项能模块化运行,准确/可靠性高
注意:axios在实际运行时,会把参数名和值,拼接到 url?参数名=值
<body>
<script>
axios({
url:'目标资源地址',
params:{
参数名:值,
}
})
.then((result) => {
//对服务器返回的数据做后续处理
})
</script>
</body>
语法格式案例
<body>
<p class='6'></p>
<!-- 1. 引入axios库 -->
<script src='https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js'></script>
<!-- 2. 在网页JavaScript中使用axios函数 -->
<script>
axios({
url:'https://hmajax.itheima.net/api/city',
// 配置查询参数
params:{
pname:'河北省'
}
})
//接收返回结果
.then((result) => {
console.log(result)
console.log(result.data.list)
console.log(result.data.list.join(`<br>`))
document.querySelector('.6').innerHTML = result.data.list.join(`<br>`)
})
</script>
</body>
案例:多条件查询
使用axios查询参数params,在params中添加多对key value参数,实现多个条件查询参数传递
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>案例_地区查询</title>
<link rel="stylesheet" href="bttps://can.jsaeiiVr.neL/np/bootstrap@5.1.3/dist/css/bootstrap.min.css">
<style>
:root {
font-size: 15px;
}
body {
padding-top: 15px;
}
</style>
</head>
<body>
<div class="container">
<form id="editForm" class= "row">
<!--输入省份名字-->
<div class="mb-3 col">
<label class="form-label">省份名字</ label>
<input type="text" value="北京" name="province"class="form-control province" placeholder="请输入省份名称"/>
</div>
<!-- 输入城市名字-->
<div class="mb-3 col">
<label class="form-label">城市名字</label>
<input type="text" value="北京市" name="city"class="form-control city" placeholder="请输入城市名称"/>
</div>
</form>
<button type="button" class="btn btn-primary sel-btn">查询</button>
<br><br>
<p>地区列表:</p>
<ul class="list-group" >
<!--示例地区-->
<li class="list-group-item">东城区</li></ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js "></script>
<script>
/*
获取地区列表:http://hmajax.itheima.net/api/area
查询参数:
pname:省份或直辖市名字
cname:城市名字
*/
// 目标:
//目标:根据省份和城市名字,查询地区列表
// 1.查询按钮-点击事件
document.querySelector('.sel-btn').addEventListener('click',()=>{
// 2.获取省份和城市名字
let pName = document.querySelector('.province').value
let cName = document.querySelector('.city').value
// 3.基于axios请求地区列表数据
axios({
url:'http://hmajax.itheima.net/api/area',
params: {
pname: pName,
cname: cName
}
})
.then(result => {
// console.log(result)打印确认一下
//4.把数据转li标签插入到页面上
let list = result.data.list
console.log(list)
let theLi = list.map(areaName => `<li class="list-group-item">${areaName}</li>`).join('')
console.log(theLi)
document.querySelector('.list-group').innerHTML = theLi
})
})
</script>
</body>
</html>
代码优化
在ES6的对象中,当属性名与变量名同名时,可以使用简写
属性名是接口要求的不能改,所以可以更改自定义的变量名
<html>
<body>
<script>
document.querySelector('.sel-btn').addEventListener('click',()=>{
// 变量名改为与属性名一致
let pname = document.querySelector('.province').value
let cname = document.querySelector('.city').value
// 3.基于axios请求地区列表数据
axios({
url:'http://hmajax.itheima.net/api/area',
params: {
// 当左侧属性名,与右侧value变量名相同时,可以简写只写一个
// pname: pname,
// cname: cname
pname,
cname
}
})
.then(result => {
let list = result.data.list
console.log(list)
let theLi = list.map(areaName => `<li class="list-group-item">${areaName}</li>`).join('')
console.log(theLi)
document.querySelector('.list-group').innerHTML = theLi
})
})
</script>
</body>
</html>
axios的请求方法method
前面都是从服务器“拿”(获取)数据,怎样把数据“存”(提交、保存)到服务器呢?
请求方法:端对服务器,实现不同的资源请求执行操作
通过Axios库中不同的请求方法,实现由端向服务器获取、提交、修改数据
请求方法 | 对应操作 |
---|---|
GET | 获取数据 |
POST | 提交数据 |
PUT | 修改数据(全部/全局) |
DELETE | 删除数据 |
PATCH | 修改数据(部分) |
设置请求方法
url:请求的URL网址 method:设置请求的方法,GET是默认的,可以省略(不区分大小写) data:提交数据
注意区分:params和data
method不区分大小写,get可以省略,属性值为字符串,记得加上引号
<body>
<script>
axios({
url:'目标资源地址',
method:'请求方法', //如果是 method:'get'的话,可以省略,所以前面条件查询没有写
data:{
参数名:值,
}
})
.then((result) => {
//对服务器返回的数据做后续处理
})
</script>
</body>
案例:数据提交-注册账号
需求:通过axios提交用户名和密码,完成注册功能
注册用户URL地址: http://hmajax.itheima.net/api/register
请求方法:POST
参数名:
username用户名(中英文和数字组成,最少8位)
password密码(最少6位)
<html>
<body>
<button class="btn">注册用户</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js "></script>
<script>
/*
注册用户:http: // hmajax.itheima.net/api/register
请求方法:POST
参数名:username:用户名(中英文和数字组成,最少8位)
password:密码(最少6位)
目标:点击按钮,通过axios提交用户和密码,完成注册
*/
// 给按钮绑定点击事件
document.querySelector('.btn').addEventListener('click',()=>{
axios({
url:'http://hmajax.itheima.net/api/register',
// 指定请求方法,以post的方式
method:'post'
// 提交数据,用data属性
data:{
username: 'itheima789',
password: '123456',
}
})
.then(result => {
console.log(result)
let list = result.data.list
console.log(list)
})
})
</script>
</body>
</html>
提交和查询总结
- 最常用的2个请求方法:POST提交数据,GET查询数据
- axios的核心配置包括:
- url:请求 URL 网址
- method:请求方法,GET可以省略(不区分大小写)
- params:查询参数
- data:提交数据
GET查询数据
<body>
<script>
axios({
url:'目标资源地址',
method:'get', //可以省略,所以前面条件查询没有写
params:{
参数名:值,
}
})
</script>
</body>
POST提交数据
<body>
<script>
axios({
url:'目标资源地址',
method:'post',
data:{
参数名:值,
}
})
</script>
</body>
axios的错误处理catch
目的:将服务器返回的错误信息,通过axios处理后,直观给到终端操作的用户
语法:在.then
方法的后面,通过点语法,调用.catch
方法,传入回调函数并定义形参
注意:区分开浏览器产生的报错信息,和Axios产生的错误信息,服务器返回的报错信息在Axios中
<body>
<script>
axios({
// 请求选项
})
.then((result) => {
//对服务器返回的数据做后续处理
})
.catch((error) => {
//处理错误
})
</script>
</body>
案例:数据提交-注册账号-返回报错-用户已注册
需求:通过axios,将服务器返回的用户已注册报错,展示给用户
当出现axios错误时,控制台一共会出现两段错误信息:
第一段(上面一段)为浏览器报错,它是没有服务器返回的错误原因,不管它
而在下面一段(第二段)是axios捕获(catch)到的错误信息,是一个对象,
- 在response属性的data属性,有报错原因
- 我们要取到它,再反馈给用户
- 通过catch方法捕获错误信息(错误信息传至形参error)
(错误信息不再爆红,之前爆红 显示Uncaught(in pormise),未捕获)
<html>
<body>
<button class="btn">注册用户</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js "></script>
<script>
/*
注册用户:http: // hmajax.itheima.net/api/register
请求方法:POST
参数名:username:用户名(中英文和数字组成,最少8位)
password:密码(最少6位)
目标:点击按钮,通过axios提交用户和密码,完成注册
需求:使用axios错误处理语法,拿到报错信息,弹框反馈给用户
*/
// 给按钮绑定点击事件
document.querySelector('.btn').addEventListener('click',()=>{
axios({
url:'http://hmajax.itheima.net/api/register',
// 指定请求方法,以post的方式
method:'post'
// 提交数据,用data属性
data:{
username: 'itheima789',
password: '123456',
}
})
.then(result => {
console.log(result)
let list = result.data.list
console.log(list)
})
.catch(error => {
// 处理错误信息
console.log(error)
console.log(error.response.data.message) //把错误原因取出error.response.data.message
alert(error.response.data.message) //用提示框提示用户alert
})
})
</script>
</body>
</html>
HTTP协议-请求报文
HTTP协议:规定了 浏览器发送 及 服务器返回 的内容格式
请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容,服务器将使用约定的协议格式来解析请求报文
请求报文解析出来的内容案例:
//请求行
//请求方法,post=提交数据,url网址=访问资源地址=注册,自动携带的http1.1协议
PoST http://hmajax.itheima.net/api/register HTTP/1.1
//请求头
//自动生成的键值对
Host: hmajax.itheima.net
Connection: keep-alive
Content-Length: 46
Accept: application/json,text/plain,*/*
User-Agent:Nozilla/5.0 (windows NT 10.0; win64; x64) ApplewebKit/537.36(KHTML,like Gecko) Chrome/107.0.0.0safari/537.36
//规定的是这次请求携带的数据类型,是json字符串
Content-Type: application/json
origin: http:/ /127.0.0.1:550e
Referer: http: / /127.8.0.1:550e/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
//空行
//请求体
//一个空行后面,就是携带的json字符串了
//axios在运行时会把代码中的data对象转成json字符串携带到请求报文中
{ "username" : "itheima887" ,"password" : "7654321"}
axios内部的源码在运行的时候,就是将代码中的对象,转成json字符串,加到请求报文当中
请求报文的组成部分有:
- 请求行:请求方法、URL、协议
- 请求头:以键值对的格式携带的附加信息,比如:Content-Type
- 空行:分隔请求头,空行之后的是发送给服务器的资源
- 请求体:发送的资源
通过浏览器调试查看请求报文
使用上一节的案例代码,在执行报错后,打开浏览器调试工具
浏览器里面点击发送请求,触发之后点:
网络-->fetch/XHR-->选中某一个请求-->标头(看请求头,载荷看请求体)-->点击查看源代码(点击后变成查看解析结果)
发现,url中的部分内容(协议 http://)经浏览器格式化
下方会列出,浏览器刚刚的动作,所涉及的相关AJAX请求
在调试工具中,主要查看:标头 载荷 响应
通过浏览器查看请求报文定位错误
学会使用浏览器调试,查看请求报文来定位错误,并修改源码
把input框type改成text可以看到密码
HTTP协议-响应报文
服务器返回对应的内容时,也有相应的响应报文
HTTP协议:规定了 浏览器发送 及 服务器返回 的内容格式
响应报文:服务器按照HTTP协议要求的格式,返回给浏览器的内容,浏览器将使用约定的协议格式来解析响应报文
与请求报文类似,响应报文的组成部分有:
- 响应行(状态行):协议、HTTP响应状态码、状态信息
- 响应头:以键值对的格式携带的附加信息,比如:Content-Type
- 空行:分隔响应头,空行之后的是服务器返回的资源
- 响应体:返回的资源
//响应行(状态行)
//协议 + HTTP协议状态码 + 状态文本信息
HTTP/1.1 400 Bad Request
//响应头
//自动生成的键值对
Server: nginx
Date: wed,89 Nov 2022 13:26:06 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 54
connection: keep-alive
Vary: origin
Access-Control-Allow-Origin: http://127.8.0.1:558e
Access-control-Allow-Credentials : true
x-frame-options : SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
x-download-options: noopen
x-readtime: 16
//空行
//响应体
//内容数据json字符串
{"code" :18805, "message":"账号被占用” , "data" : null}
响应状态码
- 响应报文也分成四部分
- 其中响应行中携带HTTP响应状态码
- 响应状态码表示请求是否成功
- 关注2和4开头的(200、404)
- 客户端错误,客户端可以理解为浏览器
状态码 | 说明 |
---|---|
1xx | 信息 |
2xx | 成功 |
3xx | 重定向信息 |
4xx | 客户端错误(浏览器) |
5xx | 服务端错误 |
HTTP响应状态码:用来表明请求是否成功完成
比如:404 (服务器找不到资源)
接口文档
接口文档:描述接口的文章
接口:使用AJAX和服务器通信时,使用的URL、请求方法、以及参数
接口是项目中,前后端约定的数据传参
axios源码发现data属性值为对象,内部会把对象转成json字符串,携带给服务器
语法格式案例
<html>
<body>
<button class="btn">用户登录</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js "></script>
<script>
document.querySelector('.btn').addEventListener('click',()=>{
//用户登录
axios({
url:'http://hmajax.itheima.net/api/login',
method:'post',
data:{
username:'itheima007',
password:'7654321'
}
})
})
</script>
</body>
</html>
已注册,实操登录
对照接口文档,填入相关信息:url、请求方法、请求体数据
没有使用then方法捕获,但可以在浏览器中直接查看响应
查看请求载荷(请求体)(需要查看源代码),发现已经转成json字符串
传参+接口
实际生产案例-用户登录
先确认完成效果(先向产品经理确认需求,向后端确认接口文档的要求)
案例效果
- 用户名长度需要大于等于8
- 密码长度需要大于等于6
- 登录成功的提示
- 用户名或密码错误的提示
前端代码目标(根据后端接口文档写前端功能)
- 点击登录时,判断用户名是否符合接口协议(用户名、密码长度)
- 提交数据与服务器通信
- 提示服务器返回的信息
案例&思路:
- 已预先使用bootstrap编写相关标签和样式,做好页面
- 需要用到标签时,到浏览器调试上找即可,右键标签>检查元素
- 面对嵌套多层的对象,可以在浏览器调试中,找到需要的属性并右键,选择复制属性路径
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例_登录</title>
<!-- 引入bootstrap.css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css">
<!-- 公共 -->
<style>
html,
body {
background-color: #EDF0F5;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 520px;
height: 540px;
background-color: #fff;
padding: 60px;
box-sizing: border-box;
}
.container h3 {
font-weight: 900;
}
</style>
<!-- 表单容器和内容 -->
<style>
.form_wrap {
color: #8B929D !important;
}
.form-text {
color: #8B929D !important;
}
</style>
<!-- 提示框样式 -->
<style>
.alert {
transition: .5s;
opacity: 0;
}
.alert.show {
opacity: 1;
}
</style>
</head>
<body>
<div class="container">
<h3>欢迎-登录</h3>
<!-- 登录结果-提示框 -->
<div class="alert alert-success" role="alert">
提示消息
</div>
<!-- 表单 -->
<div class="form_wrap">
<form>
<div class="mb-3">
<label for="username" class="form-label">账号名</label>
<input type="text" class="form-control username">
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<input type="password" class="form-control password">
</div>
<button type="button" class="btn btn-primary btn-login"> 登 录 </button>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
// 1.1 登录-点击事件绑定,在浏览器中找到类名,复制过来
document.querySelector('.btn-login').addEventListener('click', () => {
// 1.2 获取用户名和密码
const username = document.querySelector('.username').value
const password = document.querySelector('.password').value
// console.log(username, password)
// 1.3 判断长度
if (username.length < 8) {
console.log('用户名必须大于等于8位')
return // 阻止代码继续执行
}
if (password.length < 6) {
console.log('密码必须大于等于6位')
return // 阻止代码继续执行
}
// 1.4 基于axios提交用户名和密码
// console.log('提交数据到服务器')
axios({
url: 'http://hmajax.itheima.net/api/login',
method: 'POST',
data: {
username,
password
}
}).then(result => {
console.log(result) //登陆成功
console.log(result.data.message)//在调试中确认需要哪个属性值后,右键复制属性路径过来
}).catch(error => {
console.log(error) //登陆失败
console.log(error.response.data.message)
})
})
</script>
</body>
</html>
- 上面案例服务器返回的信息都是提示在调试中,下面案例提示给用户
- 通过元素检查,确认是通过bootstrap实现
- 通过样式检查,叠加元素检查,确认样式变化的相关类名
- 4个地方需要用到提示框
- 通过函数封装,实现提示框复用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例_登录_提示消息</title>
<!-- 引入bootstrap.css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css">
<!-- 公共 -->
<style>
html,
body {
background-color: #EDF0F5;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 520px;
height: 540px;
background-color: #fff;
padding: 60px;
box-sizing: border-box;
}
.container h3 {
font-weight: 900;
}
</style>
<!-- 表单容器和内容 -->
<style>
.form_wrap {
color: #8B929D !important;
}
.form-text {
color: #8B929D !important;
}
</style>
<!-- 提示框样式 -->
<style>
.alert {
transition: .5s;
opacity: 0;
}
.alert.show {
opacity: 1;
}
</style>
</head>
<body>
<div class="container">
<h3>欢迎-登录</h3>
<!-- 登录结果-提示框 -->
<div class="alert alert-success" role="alert">
提示消息
</div>
<!-- 表单 -->
<div class="form_wrap">
<form>
<div class="mb-3">
<label for="username" class="form-label">账号名</label>
<input type="text" class="form-control username">
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<input type="password" class="form-control password">
</div>
<button type="button" class="btn btn-primary btn-login"> 登 录 </button>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
// 目标2:使用提示框,反馈提示消息
// 2.1 获取提示框
const myAlert = document.querySelector('.alert')
/**
* 2.2 封装提示框函数,重复调用,满足提示需求
* 功能:
* 1. 显示提示框
* 2. 不同提示文字msg,和成功绿色失败红色isSuccess(true成功,false失败)
* 3. 过2秒后,让提示框自动消失
*/
function alertFn(msg, isSuccess) { //alertFn() 函数,两个形参,前面是显示信息msg,后面是样式
// 1> 显示提示框
myAlert.classList.add('show') //通过浏览器元素和样式检查,确认bootstrap的弹框变化是show类名控制
// 2> 实现细节
myAlert.innerText = msg
const bgStyle = isSuccess ? 'alert-success' : 'alert-danger' //声明true和false时的样式
myAlert.classList.add(bgStyle)
// 3> 过2秒隐藏
setTimeout(() => {
myAlert.classList.remove('show')
// 提示:避免类名冲突,重置背景色
myAlert.classList.remove(bgStyle)
}, 2000)
}
// 1.1 登录-点击事件
document.querySelector('.btn-login').addEventListener('click', () => {
// 1.2 获取用户名和密码
const username = document.querySelector('.username').value
const password = document.querySelector('.password').value
// console.log(username, password)
// 1.3 判断长度
if (username.length < 8) {
alertFn('用户名必须大于等于8位', false) //调用alertFn() 函数,并传参
console.log('用户名必须大于等于8位') //需要用到提示框地方
return // 阻止代码继续执行
}
if (password.length < 6) {
alertFn('密码必须大于等于6位', false) //调用alertFn() 函数,并传参
console.log('密码必须大于等于6位') //需要用到提示框地方
return // 阻止代码继续执行
}
// 1.4 基于axios提交用户名和密码
// console.log('提交数据到服务器')
axios({
url: 'http://hmajax.itheima.net/api/login',
method: 'POST',
data: {
username,
password
}
}).then(result => {
alertFn(result.data.message, true) //调用alertFn() 函数,并传参
console.log(result)
console.log(result.data.message) //需要用到提示框地方
}).catch(error => {
alertFn(error.response.data.message, false) //调用alertFn() 函数,并传参
console.log(error)
console.log(error.response.data.message) //需要用到提示框地方
})
})
</script>
</body>
</html>
快速通过form-serialize
插件收集表单元素的值
serialize翻译:连载
form-serialize
插件作用:快速收集表单元素的值
插件使用:
- 先引入网页中
- 使用
serialize
函数,有两个形参 - 第一个形参是,告诉插件,需要获取的是哪一个表单域内的表单元素的值,所以传的是表单对象
- 第二个形参是,传配置对象,主要常用配置对象是
hash
和empty
插件效果:
- 代码引入并运行后,会将表单域内表单元素的值,收集为一个对象
- 需要使用哪个表单元素值,只需要找到对应的属性,就能拿到值
打印获取到的表单数据(表单元素的值),通过确认需要获取的样式,以确认插件的形参配置
通过打印获取到的表单数据(表单元素的值),我们确认了:
- 表单元素需要设置name属性,form被获取为对象的属性名
- name属性值虽然可以随便写,但是实际开发中,这个表单元素收集到的值,将会提交给服务器传给后端
- 因为接口文档规定了参数名,所以不如参数名一步到位,将name属性的值,设置成与接口文档的参数名一致
- hash 设置获取数据结构
- empty 设置是否获取空值
配置对象中的hash属性用于设置获取数据的结构:
- 为true时,获取数据为JS对象
- 为false时,获取数据为查询字符串
- 一般使用true,表单获取的数据会被提交到服务器,将被携带在请求体,一般要求传一个对象
empty属性设置是否获取空值(表单元素的值为空)
- 为true时,获取空值(推荐)
- 为false时,不获取空值;
- 获取空值时,即使表单元素的值为空,也会将相应的字段提交,保证数据的结构和标签的结构一致
- 如果不获取空值,而表单元素的值均为空,则返回空对象(不是null)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例_登录_提示消息</title>
<!-- 引入bootstrap.css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css">
<!-- 公共 -->
<style>
html,
body {
background-color: #EDF0F5;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 520px;
height: 540px;
background-color: #fff;
padding: 60px;
box-sizing: border-box;
}
.container h3 {
font-weight: 900;
}
</style>
<!-- 表单容器和内容 -->
<style>
.form_wrap {
color: #8B929D !important;
}
.form-text {
color: #8B929D !important;
}
</style>
<!-- 提示框样式 -->
<style>
.alert {
transition: .5s;
opacity: 0;
}
.alert.show {
opacity: 1;
}
</style>
</head>
<body>
<div class="container">
<h3>欢迎-登录</h3>
<!-- 登录结果-提示框 -->
<div class="alert alert-success" role="alert">
提示消息
</div>
<!-- 表单 -->
<div class="form_wrap">
<form>
<div class="mb-3">
<label for="username" class="form-label">账号名</label>
<input type="text" class="form-control username">
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<input type="password" class="form-control password">
</div>
<button type="button" class="btn btn-primary btn-login"> 登 录 </button>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
// 目标2:使用提示框,反馈提示消息
// 2.1 获取提示框
const myAlert = document.querySelector('.alert')
/**
* 2.2 封装提示框函数,重复调用,满足提示需求
* 功能:
* 1. 显示提示框
* 2. 不同提示文字msg,和成功绿色失败红色isSuccess(true成功,false失败)
* 3. 过2秒后,让提示框自动消失
*/
function alertFn(msg, isSuccess) {
// 1> 显示提示框
myAlert.classList.add('show')
// 2> 实现细节
myAlert.innerText = msg
const bgStyle = isSuccess ? 'alert-success' : 'alert-danger'
myAlert.classList.add(bgStyle)
// 3> 过2秒隐藏
setTimeout(() => {
myAlert.classList.remove('show')
// 提示:避免类名冲突,重置背景色
myAlert.classList.remove(bgStyle)
}, 2000)
}
// 1.1 登录-点击事件
document.querySelector('.btn-login').addEventListener('click', () => {
// 1.2 获取用户名和密码
const username = document.querySelector('.username').value
const password = document.querySelector('.password').value
// console.log(username, password)
// 1.3 判断长度
if (username.length < 8) {
alertFn('用户名必须大于等于8位', false)
console.log('用户名必须大于等于8位')
return // 阻止代码继续执行
}
if (password.length < 6) {
alertFn('密码必须大于等于6位', false)
console.log('密码必须大于等于6位')
return // 阻止代码继续执行
}
// 1.4 基于axios提交用户名和密码
// console.log('提交数据到服务器')
axios({
url: 'http://hmajax.itheima.net/api/login',
method: 'POST',
data: {
username,
password
}
}).then(result => {
alertFn(result.data.message, true)
console.log(result)
console.log(result.data.message)
}).catch(error => {
alertFn(error.response.data.message, false)
console.log(error)
console.log(error.response.data.message)
})
})
</script>
</body>
</html>
登录案例-整合form-serialize来获取表单
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>案例_登录_插件使用</title>
<!-- 引入bootstrap.css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css">
<!-- 公共 -->
<style>
html,
body {
background-color: #EDF0F5;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 520px;
height: 540px;
background-color: #fff;
padding: 60px;
box-sizing: border-box;
}
.container h3 {
font-weight: 900;
}
</style>
<!-- 表单容器和内容 -->
<style>
.form_wrap {
color: #8B929D !important;
}
.form-text {
color: #8B929D !important;
}
</style>
<!-- 提示框样式 -->
<style>
.alert {
transition: .5s;
opacity: 0;
}
.alert.show {
opacity: 1;
}
</style>
</head>
<body>
<div class="container">
<h3>欢迎-登录</h3>
<!-- 登录结果-提示框 -->
<div class="alert alert-success" role="alert">
提示消息
</div>
<!-- 表单,form标签 -->
<div class="form_wrap">
<form class="login-form">
<div class="mb-3">
<label for="username" class="form-label">账号名</label>
<!-- 加name属性 -->
<input type="text" class="form-control username" name="username">
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<!-- 加name属性 -->
<input type="password" class="form-control password" name="password">
</div>
<button type="button" class="btn btn-primary btn-login"> 登 录 </button>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- 3.1 引入插件 -->
<script src="./lib/form-serialize.js"></script>
<script>
// 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
// 目标2:使用提示框,反馈提示消息
// 目标3:使用form-serialize插件,收集用户名和密码
// 2.1 获取提示框
const myAlert = document.querySelector('.alert')
/**2.2 封装提示框函数,重复调用,满足提示需求
* 功能:
* 1. 显示提示框
* 2. 不同提示文字msg,和成功绿色失败红色isSuccess(true成功,false失败)
* 3. 过2秒后,让提示框自动消失
*/
function alertFn(msg, isSuccess) {
// 1> 显示提示框
myAlert.classList.add('show')
// 2> 实现细节
myAlert.innerText = msg
const bgStyle = isSuccess ? 'alert-success' : 'alert-danger'
myAlert.classList.add(bgStyle)
// 3> 过2秒隐藏
setTimeout(() => {
myAlert.classList.remove('show')
// 提示:避免类名冲突,重置背景色
myAlert.classList.remove(bgStyle)
}, 2000)
}
// 1.1 登录-点击事件
document.querySelector('.btn-login').addEventListener('click', () => {
// 3.2 使用serialize函数,收集登录表单里用户名和密码
// 参数1:获取哪个表单的数据,通过class类名获取表单
// 通过打印获取到的表单数据(表单元素的值),我们确认了,表单元素需要设置name属性,form被获取为对象的属性名
// 建议name属性的值,最好和接口文档的参数名一致
// 参数2:配置对象
const form = document.querySelector('.login-form')
//配置对象,hash true是告诉插件,获取表单的值,形成对象,empty true是为了获取空值,让数据结构一致,使用data变量接收
const data = serialize(form, { hash: true, empty: true })
console.log(data) // 打印获取到的表单数据(表单元素的值)
// {username: 'itheima007', password: '7654321'}
// 解构赋值,同名参数,从对象里面的值,变为一个变量,让下面条件判断长度的变量赋予上值,替代document.querySelector('.username').value
// const { username: username, password: password } = data
// 简写
const { username, password } = data
// 1.2 获取用户名和密码
// const username = document.querySelector('.username').value
// const password = document.querySelector('.password').value
console.log(username, password)
// 1.3 判断长度
if (username.length < 8) {
alertFn('用户名必须大于等于8位', false)
console.log('用户名必须大于等于8位')
return // 阻止代码继续执行
}
if (password.length < 6) {
alertFn('密码必须大于等于6位', false)
console.log('密码必须大于等于6位')
return // 阻止代码继续执行
}
// 1.4 基于axios提交用户名和密码
// console.log('提交数据到服务器')
axios({
url: 'http://hmajax.itheima.net/api/login',
method: 'POST',
data: {
username,
password
}
}).then(result => {
alertFn(result.data.message, true)
console.log(result)
console.log(result.data.message)
}).catch(error => {
alertFn(error.response.data.message, false)
console.log(error)
console.log(error.response.data.message)
})
})
</script>
</body>
</html>