综合案例 --- 图书管理(CRUD) + Bootstrap5 模态框(Doal)
1. 图书列表
book_manager.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bootstrap5-图书管理</title>
<!-- 字体图标 -->
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3736578_vxpb728fcyh.css">
<!-- 引入bootstrap.css -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 主体区域,Bootstrap 中的tables-->
<div class="container">
<h1>图书管理</h1>
<button type="button" class="btn btn-primary add-btn">+ 添加</button>
<table class="table">
<thead>
<tr class="table-active">
<th scope="col">序号</th>
<th scope="col">书名</th>
<th scope="col">作者</th>
<th scope="col">出版社</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody class="list">
<tr>
<th scope="row">1</th>
<td>JavaScript程序设计</td>
<td>玛特福利伦比</td>
<td>人民邮电出版时</td>
<td>
<span style="color: darksalmon">删除</span>
<span style="color: dodgerblue">编辑</span>
</td>
</tr>
</tbody>
<tfoot>
...
</tfoot>
</table>
</div>
<!-- 新增时的弹出框 -->
<!-- 引入axios.js -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 引入form-serialize.js -->
<script src="form-seralize/index.js"></script>
<!-- 引入bootstrap.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.min.js"></script>
<!-- 核心逻辑 -->
<script src="js/index.js"></script>
</body>
</html>
index.js
/*
* 功能一: 渲染图书列表
* 1. 用 axios 向后端发送请求,获取图书列表数据
* 2. 循环列表数据生成标签并渲染页面
* */
function getBookList() {
axios({
url: "http://hmajax.itheima.net/api/books",
params: {
creator: "老孙"
}
})
.then(result => {
const bookList = result.data.data
console.log(bookList)
// 1. 循环返回的数据构建标签结构
const htmlStr = bookList.map((item, index) => {
return `<tr>
<th scope="row">${index + 1}</th>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td>
<span style="color: darksalmon">删除</span>
<span style="color: dodgerblue">编辑</span>
</td>
</tr>`
}).join("")
// 2. 将标签结构插入到 <tbody> 标签中
document.querySelector(".list").innerHTML = htmlStr
})
}
// 页面渲染的时候就需要调用 getBookList 获取图书列表
getBookList()
2. 新增图书
book_manager.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bootstrap5-图书管理</title>
<!-- 字体图标 -->
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3736578_vxpb728fcyh.css">
<!-- 引入bootstrap.css -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 主体区域,Bootstrap 中的tables-->
<div class="container">
<h1>图书管理</h1>
<!-- 1. 将按钮替换成 modal 中的空值按钮,用于空值模态框的显示和隐藏 -->
<button type="button" class="btn btn-primary add-btn" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">+ 添加</button>
<table class="table">
<thead>
<tr class="table-active">
<th scope="col">序号</th>
<th scope="col">书名</th>
<th scope="col">作者</th>
<th scope="col">出版社</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody class="list">
</tbody>
</table>
</div>
<!-- 新增时的弹出框,Bootstrap 中的modal -->
<div class="modal fade add-modal" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">添加图书</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form class="add-form">
<div class="mb-3">
<label for="book-name" class="col-form-label">书名:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="book-name" name="bookname">
</div>
<div class="mb-3">
<label for="author-name" class="col-form-label">作者:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="author-name" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="col-form-label">出版社:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="publisher" name="publisher">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary save-btn">保存</button>
</div>
</div>
</div>
</div>
<!-- 引入axios.js -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 引入form-serialize.js -->
<script src="form-seralize/index.js"></script>
<!-- 引入bootstrap.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.min.js"></script>
<!-- 核心逻辑 -->
<script src="js/index.js"></script>
</body>
</html>
index.js
/*
* 功能一: 渲染图书列表
* 1. 用 axios 向后端发送请求,获取图书列表数据
* 2. 循环列表数据生成标签并渲染页面
* */
const creator = "老孙"
function getBookList() {
axios({
url: "http://hmajax.itheima.net/api/books",
params: {
creator
}
})
.then(result => {
const bookList = result.data.data
// 1. 循环返回的数据构建标签结构
const htmlStr = bookList.map((item, index) => {
return `<tr>
<th scope="row">${index + 1}</th>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td>
<span style="color: darksalmon">删除</span>
<span style="color: dodgerblue">编辑</span>
</td>
</tr>`
}).join("")
// 2. 将标签结构插入到 <tbody> 标签中
document.querySelector(".list").innerHTML = htmlStr
})
}
// 页面渲染的时候就需要调用 getBookList 获取图书列表
getBookList()
/*
* 功能二: 新增图书
* 1. 点击添加按钮弹出模态框及关闭模态框
* 2. 点击保存时
* 2.1 发送 post 请求,将信息提交到服务器
* 2.2 关闭模态框
* 2.3 重新发送请求渲染图书列表
* */
// 想要控制模态框,需要先创建弹框对象
const addModalDom = document.querySelector(".add-modal")
const addModal = new bootstrap.Modal(addModalDom)
document.querySelector(".save-btn").addEventListener("click", () => {
// 使用 form-serialize 插件快速收集from表单中的表单数据
const addForm = document.querySelector(".add-modal .add-form")
const bookObj = serialize(addForm, {hash: true, empty: true})
// 发送数据到后端,保存在数据库
axios({
url: "http://hmajax.itheima.net/api/books",
method: "post",
data: {
...bookObj,
creator
}
})
.then(result => {
console.log(result)
// 请求成功后
if (result.status === 201) {
// 将输入框中的数据清空
addForm.reset()
// 隐藏模态框
addModal.hide()
// 重新发送请求渲染图书列表
getBookList()
}
})
})
3. 删除图书
book_manager.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bootstrap5-图书管理</title>
<!-- 字体图标 -->
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3736578_vxpb728fcyh.css">
<!-- 引入bootstrap.css -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 主体区域,Bootstrap 中的tables-->
<div class="container">
<h1>图书管理</h1>
<!-- 1. 将按钮替换成 modal 中的空值按钮,用于空值模态框的显示和隐藏 -->
<button type="button" class="btn btn-primary add-btn" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">+ 添加</button>
<table class="table">
<thead>
<tr class="table-active">
<th scope="col">序号</th>
<th scope="col">书名</th>
<th scope="col">作者</th>
<th scope="col">出版社</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody class="list">
</tbody>
</table>
</div>
<!-- 新增时的弹出框,Bootstrap 中的modal -->
<div class="modal fade add-modal" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">添加图书</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form class="add-form">
<div class="mb-3">
<label for="book-name" class="col-form-label">书名:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="book-name" name="bookname">
</div>
<div class="mb-3">
<label for="author-name" class="col-form-label">作者:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="author-name" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="col-form-label">出版社:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="publisher" name="publisher">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary save-btn">保存</button>
</div>
</div>
</div>
</div>
<!-- 引入axios.js -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 引入form-serialize.js -->
<script src="form-seralize/index.js"></script>
<!-- 引入bootstrap.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.min.js"></script>
<!-- 核心逻辑 -->
<script src="js/index.js"></script>
</body>
</html>
index.js
/*
* 功能一: 渲染图书列表
* 1. 用 axios 向后端发送请求,获取图书列表数据
* 2. 循环列表数据生成标签并渲染页面
* */
const creator = "老孙"
function getBookList() {
axios({
url: "http://hmajax.itheima.net/api/books",
params: {
creator
}
})
.then(result => {
const bookList = result.data.data
// 1. 循环返回的数据构建标签结构,使用自定义数据将id绑定在每一行的 tr 标签上
const htmlStr = bookList.map((item, index) => {
return `<tr data-id=${item.id}>
<th scope="row">${index + 1}</th>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td>
<span class="del" style="color: darksalmon">删除</span>
<span class="edit" style="color: dodgerblue">编辑</span>
</td>
</tr>`
}).join("")
// 2. 将标签结构插入到 <tbody> 标签中
document.querySelector(".list").innerHTML = htmlStr
})
}
// 页面渲染的时候就需要调用 getBookList 获取图书列表
getBookList()
/*
* 功能二: 新增图书
* 1. 点击添加按钮弹出模态框及关闭模态框
* 2. 点击保存时
* 2.1 发送 post 请求,将信息提交到服务器
* 2.2 关闭模态框
* 2.3 重新发送请求渲染图书列表
* */
// 想要控制模态框,需要先创建弹框对象
const addModalDom = document.querySelector(".add-modal")
const addModal = new bootstrap.Modal(addModalDom)
document.querySelector(".save-btn").addEventListener("click", () => {
// 使用 form-serialize 插件快速收集from表单中的表单数据
const addForm = document.querySelector(".add-modal .add-form")
const bookObj = serialize(addForm, {hash: true, empty: true})
// 发送数据到后端,保存在数据库
axios({
url: "http://hmajax.itheima.net/api/books",
method: "post",
data: {
...bookObj,
creator
}
})
.then(result => {
console.log(result)
// 请求成功后
if (result.status === 201) {
// 将输入框中的数据清空
addForm.reset()
// 隐藏模态框
addModal.hide()
// 重新渲染图书列表
getBookList()
}
})
})
/*
* 功能三: 删除图书
* 1. 点击删除
* 1.1 发送请求到后端删除数据
* 1.2 重新发送请求渲染图书列表
* */
// 使用事件委托给<tbody>标签绑定事件
document.querySelector(".list").addEventListener("click", function (e) {
// 获取触发事件的目标元素,以标签上是否有del这个类名为根据进行判断,当点击的是删除元素的时候才做以下逻辑
if (e.target.classList.contains("del")) {
const deleteId = e.target.parentNode.parentNode.dataset.id
axios({
url:`http://hmajax.itheima.net/api/books/${deleteId}`,
method: "delete",
}).then(result=>{
if (result.status === 200){
getBookList()
}
})
}
})
4. 编辑图书
book_manager.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bootstrap5-图书管理</title>
<!-- 字体图标 -->
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3736578_vxpb728fcyh.css">
<!-- 引入bootstrap.css -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 主体区域,Bootstrap 中的tables-->
<div class="container">
<h1>图书管理</h1>
<!-- 1. 将按钮替换成 modal 中的空值按钮,用于空值模态框的显示和隐藏 -->
<button type="button" class="btn btn-primary add-btn" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">+ 添加</button>
<table class="table">
<thead>
<tr class="table-active">
<th scope="col">序号</th>
<th scope="col">书名</th>
<th scope="col">作者</th>
<th scope="col">出版社</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody class="list">
</tbody>
</table>
</div>
<!-- 新增时的弹出框,Bootstrap 中的modal -->
<div class="modal fade add-modal" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">添加图书</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form class="add-form">
<div class="mb-3">
<label for="book-name" class="col-form-label">书名:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="book-name" name="bookname">
</div>
<div class="mb-3">
<label for="author-name" class="col-form-label">作者:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="author-name" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="col-form-label">出版社:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control" id="publisher" name="publisher">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary save-btn">保存</button>
</div>
</div>
</div>
</div>
<div class="modal fade edit-modal" id="exampleModal2" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel2">添加图书</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form class="edit-form">
<div class="mb-3">
<!-- 给 input框 添加 name属性 -->
<input type="hidden" class="form-control id" name="id">
</div>
<div class="mb-3">
<label for="book-name2" class="col-form-label">书名:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control bookname" id="book-name2" name="bookname">
</div>
<div class="mb-3">
<label for="author-name2" class="col-form-label">作者:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control author" id="author-name2" name="author">
</div>
<div class="mb-3">
<label for="publisher2" class="col-form-label">出版社:</label>
<!-- 给 input框 添加 name属性 -->
<input type="text" class="form-control publisher" id="publisher2" name="publisher">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary edit-btn">保存</button>
</div>
</div>
</div>
</div>
<!-- 引入axios.js -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 引入form-serialize.js -->
<script src="form-seralize/index.js"></script>
<!-- 引入bootstrap.js -->
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.min.js"></script>
<!-- 核心逻辑 -->
<script src="js/index.js"></script>
</body>
</html>
index.js
/*
* 功能一: 渲染图书列表
* 1. 用 axios 向后端发送请求,获取图书列表数据
* 2. 循环列表数据生成标签并渲染页面
* */
const creator = "老孙"
function getBookList() {
axios({
url: "http://hmajax.itheima.net/api/books",
params: {
creator
}
})
.then(result => {
const bookList = result.data.data
// 1. 循环返回的数据构建标签结构
const htmlStr = bookList.map((item, index) => {
return `<tr data-id=${item.id}>
<th scope="row">${index + 1}</th>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td>
<span class="del" style="color: darksalmon">删除</span>
<span class="edit" style="color: dodgerblue">编辑</span>
</td>
</tr>`
}).join("")
// 2. 将标签结构插入到 <tbody> 标签中
document.querySelector(".list").innerHTML = htmlStr
})
}
// 页面渲染的时候就需要调用 getBookList 获取图书列表
getBookList()
/*
* 功能二: 新增图书
* 1. 点击添加按钮弹出模态框及关闭模态框
* 2. 点击保存时
* 2.1 发送 post 请求,将信息提交到服务器
* 2.2 关闭模态框
* 2.3 重新发送请求渲染图书列表
* */
// 想要控制模态框,需要先创建弹框对象
const addModalDom = document.querySelector(".add-modal")
const addModal = new bootstrap.Modal(addModalDom)
document.querySelector(".save-btn").addEventListener("click", () => {
// 使用 form-serialize 插件快速收集from表单中的表单数据
const addForm = document.querySelector(".add-modal .add-form")
const bookObj = serialize(addForm, {hash: true, empty: true})
// 发送数据到后端,保存在数据库
axios({
url: "http://hmajax.itheima.net/api/books",
method: "post",
data: {
...bookObj,
creator
}
})
.then(result => {
console.log(result)
// 请求成功后
if (result.status === 201) {
// 将输入框中的数据清空
addForm.reset()
// 隐藏模态框
addModal.hide()
// 重新渲染图书列表
getBookList()
}
})
})
/*
* 功能三: 删除图书
* 1. 点击删除
* 1.1 发送请求到后端删除数据
* 1.2 重新发送请求渲染图书列表
* */
// 使用事件委托给<tbody>标签绑定事件
document.querySelector(".list").addEventListener("click", function (e) {
// 获取触发事件的目标元素,以标签上是否有del这个类名为根据进行判断,当点击的是删除元素的时候才做以下逻辑
if (e.target.classList.contains("del")) {
const deleteId = e.target.parentNode.parentNode.dataset.id
axios({
url: `http://hmajax.itheima.net/api/books/${deleteId}`,
method: "delete",
}).then(result => {
if (result.status === 200) {
getBookList()
}
})
}
})
/*
* 功能四: 编辑图书
* 1. 点击编辑
* 1.1 发送请求到后端获取当前点击编辑的数据
* 1.2 将请求回来的图书详情数据渲染到form表单中
* 2. 修改信息后,点击保存
* 2.1 将最新的数据收集好后,发送post请求到后端保存起来
* 2.2 请求成功关闭模态框,清空表单内容
* 3. 重新发送请求渲染图书列表
* */
// 使用事件委托给<tbody>标签绑定事件
const editModalDom = document.querySelector(".edit-modal")
const editModal = new bootstrap.Modal(editModalDom)
document.querySelector(".list").addEventListener("click", function (e) {
// 获取触发事件的目标元素,以标签上是否有del这个类名为根据进行判断,当点击的是删除元素的时候才做以下逻辑
if (e.target.classList.contains("edit")) {
// 发送请求获取图书详情,并将信息填写在编辑的模态框中
const editId = e.target.parentNode.parentNode.dataset.id
axios({
url: `http://hmajax.itheima.net/api/books/${editId}`,
})
.then(result => {
if (result.status === 200) {
const bookObj = result.data.data
Object.keys(bookObj).forEach(item => {
document.querySelector(`.edit-form .${item}`).value = bookObj[item]
})
editModal.show()
}
})
}
})
// 编辑图书时,点击保存按钮
document.querySelector(".edit-modal .edit-btn").addEventListener("click", function (e) {
const editForm = document.querySelector(".edit-modal .edit-form")
const {id,bookname,author,publisher} = serialize(editForm, {hash: true, empty: true})
// 将修改后的图书对象发送到后端
axios({
url: `http://hmajax.itheima.net/api/books/${id}`,
method: "put",
data: {
bookname,
author,
publisher,
creator
}
})
.then(result => {
// 请求成功后
if (result.status === 200) {
// 将输入框中的数据清空
editForm.reset()
// 隐藏模态框
editModal.hide()
// 重新渲染图书列表
getBookList()
}
})
})
python防脱发技巧