01-综合案例:图书管理

1.1-查询图书列表
function renderBookList() {
axios
.get("http://www.liulongbin.top:3006/api/getbooks")
.then(({ data: res }) => {
document.querySelector("tbody").innerHTML = res.data
.map(item => {
return `<tr>
<th scope="row">${item.id}</th>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td>
<button type="button" class="btn btn-link btn-sm">删除</button>
</td>
</tr>`
})
.join("")
})
}
renderBookList()
1.2-封装函数获取表单参数
function getFormData() {
let inputList = document.querySelectorAll("#addForm input")
let obj = {}
inputList.forEach(item => {
obj[item.name] = item.value
})
return obj
}
1.3-新增图书
document.querySelector("#addForm").onsubmit = function(e) {
e.preventDefault()
let data = getFormData()
if (Object.values(data).some(item => item == "")) {
alert("输入框不能为空")
return
}
axios({
url: "http://www.liulongbin.top:3006/api/addbook",
method: "post",
data
}).then(res => {
if (res.data.status != 201) {
return alert(res.data.msg)
}
alert(res.data.msg)
renderBookList()
document.querySelector("#addForm").reset()
})
}
1.4-删除图书
document.querySelector(".table>tbody").onclick = function(e) {
if (e.target.classList.contains("delete")) {
let id = e.target.getAttribute("data-id")
axios({
url: "http://www.liulongbin.top:3006/api/delbook",
method: "get",
params: { id }
}).then(res => {
if (res.data.status != 200) {
return alert(res.data.msg)
}
alert(res.data.msg)
renderBookList()
})
}
}
1.5-loading效果实现
<!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>Document</title>
<link rel="stylesheet" href="./lib/bootstrap-v4.6.0.css" />
<style>
:root {
font-size: 15px;
}
body {
padding-top: 15px;
}
.loading-box {
position: fixed;
top: 30%;
left: 50%;
transform: translateX(-50%);
background-color: rgba(0, 0, 0, 0.1);
border-radius: 10px;
box-shadow: 1px 1px 3px #efefef;
display: none;
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-8">
<table
class="table table-bordered table-striped table-dark table-hover text-center"
>
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">书名</th>
<th scope="col">作者</th>
<th scope="col">出版社</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">xxx</th>
<td>xxx</td>
<td>xxx</td>
<td>xxx</td>
<td>
<button type="button" class="btn btn-link btn-sm">
删除
</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-4">
<div class="card text-white bg-secondary sticky-top">
<div class="card-header">添加新图书</div>
<form class="card-body bg-light" id="addForm">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">书名</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入图书名称"
name="bookname"
/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">作者</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入作者名字"
name="author"
/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">出版社</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入出版社名称"
name="publisher"
/>
</div>
<button class="btn btn-dark" type="submit">添加</button>
</form>
</div>
</div>
</div>
</div>
<div class="loading-box">
<div class="spinner-border m-5 text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
<script src="./lib/axios.js"></script>
<script>
function renderBookList() {
document.querySelector(".loading-box").style.display = "block"
axios
.get("http://www.liulongbin.top:3006/api/getbooks")
.then(({ data: res }) => {
console.log(res)
document.querySelector(".loading-box").style.display = "none"
document.querySelector("tbody").innerHTML = res.data
.map(item => {
return `<tr>
<th scope="row">${item.id}</th>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td>
<button type="button" data-id="${item.id}" class="btn delete btn-link btn-sm">删除</button>
</td>
</tr>`
})
.join("")
})
}
function getFormData() {
let inputList = document.querySelectorAll("#addForm input")
let obj = {}
inputList.forEach(item => {
obj[item.name] = item.value
})
return obj
}
renderBookList()
document.querySelector("#addForm").onsubmit = function(e) {
e.preventDefault()
let data = getFormData()
if (Object.values(data).some(item => item == "")) {
alert("输入框不能为空")
return
}
document.querySelector(".loading-box").style.display = "block"
axios({
url: "http://www.liulongbin.top:3006/api/addbook",
method: "post",
data
}).then(res => {
document.querySelector(".loading-box").style.display = "none"
if (res.data.status != 201) {
return alert(res.data.msg)
}
alert(res.data.msg)
renderBookList()
document.querySelector("#addForm").reset()
})
}
document.querySelector(".table>tbody").onclick = function(e) {
if (e.target.classList.contains("delete")) {
let id = e.target.getAttribute("data-id")
document.querySelector(".loading-box").style.display = "block"
axios({
url: "http://www.liulongbin.top:3006/api/delbook",
method: "get",
params: { id }
}).then(res => {
document.querySelector(".loading-box").style.display = "none"
if (res.data.status != 200) {
return alert(res.data.msg)
}
alert(res.data.msg)
renderBookList()
})
}
}
</script>
</body>
</html>
1.6-axios拦截器使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4MG10ZkQ-1650886799562)(day03.assets/1647191663866.png)]
<!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>Document</title>
<link rel="stylesheet" href="./lib/bootstrap-v4.6.0.css" />
<style>
body {
padding: 20px;
}
.loading-box {
position: fixed;
top: 30%;
left: 50%;
transform: translateX(-50%);
background-color: rgba(0, 0, 0, 0.1);
border-radius: 10px;
box-shadow: 1px 1px 3px #efefef;
display: none;
}
</style>
</head>
<body>
<button class="btn btn-primary" id="btn1">请求1</button>
<button class="btn btn-info" id="btn2">请求2</button>
<button class="btn btn-warning" id="btn3">请求3</button>
<div class="loading-box">
<div class="spinner-border m-5 text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
<script src="./lib/axios.js"></script>
<script>
axios.interceptors.request.use(
function(config) {
document.querySelector(".loading-box").style.display = "block"
return config
},
function(error) {
return Promise.reject(error)
}
)
axios.interceptors.response.use(
function(response) {
document.querySelector(".loading-box").style.display = "none"
return response
},
function(error) {
$(".loading-box").hide()
return Promise.reject(error)
}
)
document.querySelector("#btn1").onclick = function() {
axios({
url: "http://www.liulongbin.top:3009/api/news",
method: "get"
}).then(res => {
console.log(res)
})
}
document.querySelector("#btn2").onclick = function() {
axios({
url: "https://autumnfish.cn/fruitApi/fruits",
method: "get"
}).then(res => {
console.log(res)
})
}
document.querySelector("#btn3").onclick = function() {
axios({
url: "http://www.liulongbin.top:3009/api/login",
method: "post",
data:{ username:'admin',password:'123456'}
}).then(res => {
console.log(res)
})
}
</script>
</body>
</html>
1.7-axios基地址
<!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>Document</title>
<link rel="stylesheet" href="./lib/bootstrap-v4.6.0.css" />
<style>
:root {
font-size: 15px;
}
body {
padding-top: 15px;
}
.loading-box {
position: fixed;
top: 30%;
left: 50%;
transform: translateX(-50%);
background-color: rgba(0, 0, 0, 0.1);
border-radius: 10px;
box-shadow: 1px 1px 3px #efefef;
display: none;
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-8">
<table
class="table table-bordered table-striped table-dark table-hover text-center"
>
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">书名</th>
<th scope="col">作者</th>
<th scope="col">出版社</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">xxx</th>
<td>xxx</td>
<td>xxx</td>
<td>xxx</td>
<td>
<button type="button" class="btn btn-link btn-sm">
删除
</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="col-sm-4">
<div class="card text-white bg-secondary sticky-top">
<div class="card-header">添加新图书</div>
<form class="card-body bg-light" id="addForm">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">书名</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入图书名称"
name="bookname"
/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">作者</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入作者名字"
name="author"
/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">出版社</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入出版社名称"
name="publisher"
/>
</div>
<button class="btn btn-dark" type="submit">添加</button>
</form>
</div>
</div>
</div>
</div>
<div class="loading-box">
<div class="spinner-border m-5 text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
<script src="./lib/axios.js"></script>
<script>
axios.defaults.baseURL = 'http://www.liulongbin.top:3006'
function renderBookList() {
axios
.get("/api/getbooks")
.then(({ data: res }) => {
console.log(res)
document.querySelector("tbody").innerHTML = res.data
.map(item => {
return `<tr>
<th scope="row">${item.id}</th>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td>
<button type="button" data-id="${item.id}" class="btn delete btn-link btn-sm">删除</button>
</td>
</tr>`
})
.join("")
})
}
function getFormData() {
let inputList = document.querySelectorAll("#addForm input")
let obj = {}
inputList.forEach(item => {
obj[item.name] = item.value
})
return obj
}
axios.interceptors.request.use(
function(config) {
document.querySelector(".loading-box").style.display = "block"
return config
},
function(error) {
return Promise.reject(error)
}
)
axios.interceptors.response.use(
function(response) {
document.querySelector(".loading-box").style.display = "none"
return response
},
function(error) {
$(".loading-box").hide()
return Promise.reject(error)
}
)
renderBookList()
document.querySelector("#addForm").onsubmit = function(e) {
e.preventDefault()
let data = getFormData()
if (Object.values(data).some(item => item == "")) {
alert("输入框不能为空")
return
}
axios({
url: "/api/addbook",
method: "post",
data
}).then(res => {
if (res.data.status != 201) {
return alert(res.data.msg)
}
alert(res.data.msg)
renderBookList()
document.querySelector("#addForm").reset()
})
}
document.querySelector(".table>tbody").onclick = function(e) {
if (e.target.classList.contains("delete")) {
let id = e.target.getAttribute("data-id")
axios({
url: "/api/delbook",
method: "get",
params: { id }
}).then(res => {
if (res.data.status != 200) {
return alert(res.data.msg)
}
alert(res.data.msg)
renderBookList()
})
}
}
</script>
</body>
</html>
02-ajax补充知识点(面试用)
1.1-onreadstatechange事件(了解)
- 官网文档传送门:https://www.runoob.com/ajax/ajax-xmlhttprequest-onreadystatechange.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>
</head>
<body>
<script>
let xhr = new XMLHttpRequest()
console.log(xhr.readyState)
xhr.open("post", "http://www.liulongbin.top:3009/api/login")
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
console.log(xhr.readyState)
xhr.send("username=admin&password=123456")
xhr.onreadystatechange = function() {
console.log(xhr.readyState)
if (xhr.readyState == 4) {
console.log(xhr.responseText)
}
}
</script>
</body>
</html>
1.2-Ajax组成部分了解(了解)
- Ajax(阿贾克斯):全称
Asynchronous Javascript And XML(异步的js与xml)
- 说人话: 用js发送异步的网络请求
- A : Asynchronous 异步
- 同步 : 指的是代码按照从上往下顺序执行
- 异步 : 代码不会立即执行,而是要等一会儿执行
- 目前我们学过的ECMAScript只有两个语法是异步的: 定时器 与 ajax
- DOM事件也是属于异步的,但是这个是属于DOM的执行机制。所以一般在讨论js同步和异步的时候,主要以js为主,DOM一般不讨论。
- J:Javascript
- A :And
- X : XML 与 XMLHttpRequest
- XML : 解决跨平台数据传输。
- 在JSON没有出来以前, 网络传输主要以XML格式数据为主。 后来JSON问世,逐渐取代XML。 但是由于ajax技术出来的比json早,因此xml这个称呼一直保留至今
获取 json 格式的天气
参数名 | 参数说明 | 备注 |
---|
City | 查询的城市名 | 不能为空,不能写错 |
{
"data": {
"yesterday": {
"date": "15日星期三",
"high": "高温 31℃",
"fx": "无持续风向",
"low": "低温 26℃",
"fl": "<![CDATA[<3级]]>",
"type": "多云"
},
"city": "深圳",
"forecast": [
{
"date": "16日星期四",
"high": "高温 32℃",
"fengli": "<![CDATA[<3级]]>",
"low": "低温 27℃",
"fengxiang": "无持续风向",
"type": "阵雨"
},
{
"date": "17日星期五",
"high": "高温 32℃",
"fengli": "<![CDATA[<3级]]>",
"low": "低温 27℃",
"fengxiang": "无持续风向",
"type": "雷阵雨"
},
{
"date": "18日星期六",
"high": "高温 32℃",
"fengli": "<![CDATA[<3级]]>",
"low": "低温 27℃",
"fengxiang": "无持续风向",
"type": "雷阵雨"
},
{
"date": "19日星期天",
"high": "高温 32℃",
"fengli": "<![CDATA[<3级]]>",
"low": "低温 25℃",
"fengxiang": "无持续风向",
"type": "雷阵雨"
},
{
"date": "20日星期一",
"high": "高温 29℃",
"fengli": "<![CDATA[<3级]]>",
"low": "低温 24℃",
"fengxiang": "无持续风向",
"type": "阵雨"
}
],
"ganmao": "各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。",
"wendu": "30"
},
"status": 1000,
"desc": "OK"
}
获取 xml 格式菜单
- 请求地址:https://autumnfish.cn/api/food.xml
- 请求方法:get
- 请求参数:无
- 响应内容:
<?xml version="1.0" encoding="UTF-8"?>
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<description>Two of our famous Belgian Waffles with plenty of real maple syrup</description>
<calories>650</calories>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<description>Light Belgian waffles covered with strawberries and whipped cream</description>
<calories>900</calories>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
<calories>900</calories>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<description>Thick slices made from our homemade sourdough bread</description>
<calories>600</calories>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
<calories>950</calories>
</food>
</breakfast_menu>
1.3-get请求与post请求区别(掌握)
- 1.传参方式不同
- get在url后面拼接(请求行)
- post在请求体传参
- 2.大小限制不同
- get有大小限制,不同浏览器大小限制不同。 一般2-5 MB
- post没有大小限制
- 3.安全性不同
- get参数直接暴露在url,不安全(一般查询类数据都是get)
- post参数在请求体中,更加安全(一般登录注册必须是post)
- 4.传输速度不同
1.4-其他请求方法了解(掌握)
实际开发中,前端无权决定请求方法,只需要根据后台接口文档来就可以了
请求方式 | 描述 | 特点 |
---|
post | 一般用于新增数据(提交数据) | 请求体传参 |
get | 一般用于查询数据(查询数据) | 请求行(url)传参 |
delete | 一般用于删除数据 | 请求体传参 |
put | 一般用于更新全部数据 | 请求体传参 |
patch | 一般用于更新局部数据 | 请求体传参 |

今日接口文档
图书管理基地址:http://www.liulongbin.top:3006
1 图书列表
- 接口URL: /api/getbooks
- 调用方式: GET
- 参数格式:
参数名称 | 参数类型 | 是否必选 | 参数说明 |
---|
id | Number | 否 | 图书Id |
bookname | String | 否 | 图书名称 |
author | String | 否 | 作者 |
publisher | String | 否 | 出版社 |
数据名称 | 数据类型 | 说明 |
---|
status | Number | 200 成功;500 失败; |
msg | String | 对 status 字段的详细说明 |
data | Array | 图书列表 |
+id | Number | 图书Id |
+bookname | String | 图书名称 |
+author | String | 作者 |
+publisher | String | 出版社 |
{
"status": 200,
"msg": "获取图书列表成功",
"data": [
{ "id": 1, "bookname": "西游记", "author": "吴承恩", "publisher": "北京图书出版社" },
{ "id": 2, "bookname": "红楼梦", "author": "曹雪芹", "publisher": "上海图书出版社" },
{ "id": 3, "bookname": "三国演义", "author": "罗贯中", "publisher": "北京图书出版社" }
]
}
2 添加图书
- 接口URL: /api/addbook
- 调用方式: POST
- 参数格式:
参数名称 | 参数类型 | 是否必选 | 参数说明 |
---|
bookname | String | 是 | 图书名称 |
author | String | 是 | 作者 |
publisher | String | 是 | 出版社 |
数据名称 | 数据类型 | 说明 |
---|
status | Number | 201 添加成功;500 添加失败; |
msg | String | 对 status 字段的详细说明 |
{
"status": 201,
"msg": "添加图书成功"
}
3 删除图书
- 接口URL: /api/delbook
- 调用方式: GET
- 参数格式:
参数名称 | 参数类型 | 是否必选 | 参数说明 |
---|
id | Number | 是 | 图书Id |
数据名称 | 数据类型 | 说明 |
---|
status | Number | 200 删除成功;500 未指定要删除的图书Id;501 执行Sql报错;502 要删除的图书不存在; |
msg | String | 对 status 字段的详细说明 |
{
"status": 200,
"msg": "删除图书成功!"
}
### 2 添加图书
* 接口URL: /api/addbook
* 调用方式: POST
* 参数格式:
| 参数名称 | 参数类型 | 是否必选 | 参数说明 |
| --------- | -------- | -------- | -------- |
| bookname | String | 是 | 图书名称 |
| author | String | 是 | 作者 |
| publisher | String | 是 | 出版社 |
* 响应格式:
| 数据名称 | 数据类型 | 说明 |
| -------- | -------- | ---------------------------- |
| status | Number | 201 添加成功;500 添加失败; |
| msg | String | 对 status 字段的详细说明 |
* 返回示例:
```json
{
"status": 201,
"msg": "添加图书成功"
}
3 删除图书
- 接口URL: /api/delbook
- 调用方式: GET
- 参数格式:
参数名称 | 参数类型 | 是否必选 | 参数说明 |
---|
id | Number | 是 | 图书Id |
数据名称 | 数据类型 | 说明 |
---|
status | Number | 200 删除成功;500 未指定要删除的图书Id;501 执行Sql报错;502 要删除的图书不存在; |
msg | String | 对 status 字段的详细说明 |
{
"status": 200,
"msg": "删除图书成功!"
}