1.渲染列表
自己的图书数据:给自己起个外号,并告诉服务器,默认会有三本书,基于这三本书做数据的增删改查。
// 目标1:渲染图书列表
// 1.1 获取数据
// 1.2 渲染数据
const creator = '哈哈'
// 封装-获取并渲染图书列表函数
function getBooksList(){
//1.1 获取数据
axios({
url:'http://hmajax.itheima.net/api/books',
params:{
// 外号:获取对应数据
creator
}
}).then(result => {
console.log(result)
const bookList = result.data.data
console.log(bookList)
//1.2 渲染数据
const htmlStr = bookList.map((item, index) => {
return `<tr>
<td>${ index + 1}</td>
<td>${ item.bookname }</td>
<td>${ item.author }</td>
<td>${ item.publisher }</td>
<td>
<span class="del">删除</span>
<span class="edit">编辑</span>
</td>
</tr>
`
}).join('')
console.log(htmlStr)
document.querySelector('.list').innerHTML = htmlStr
})
}
// 网页加载运行,获取并渲染列表一次
getBooksList()
2.新增图书
/**
* 目标2:新增图书
* 2.1 新增弹框 -> 显示和隐藏
* 2.2 收集表达数据,并提交到服务器保存
* 2.3 刷新图书列表
*/
// 2.1 创建弹框对象
const addModalDom = document.querySelector('.add-modal')
const addModal = new bootstrap.Modal(addModalDom)
// 保存按钮 -> 点击 -> 隐藏弹框
document.querySelector('.add-btn').addEventListener('click', () => {
// 2.2 收集表单数据,并提交到服务器保存
const addForm = document.querySelector('.add-form')
const bookObj = serialize(addForm, { hash: true, empty: true})
console.log(bookObj)
// 提交到服务器
axios({
url: 'http://hmajax.itheima.net/api/books',
method: 'POST',
data: {
...bookObj,
creator
}
}).then(result => {
console.log(result)
// 2.3 添加成功后,重新请求并渲染图书列表
getBooksList()
// 重置表单
addForm.reset()
// 隐藏弹框
addModal.hide()
})
})
3.删除图书
/**
* 目标3: 删除图书
* 3.1 删除元素绑定点击事件 -> 获取图书
* 3.2 调用删除接口
* 3.3 刷新图书列表
*/
// 3.1 删除元素 -> 点击(事件委托)
document.querySelector('.list').addEventListener('click', e => {
// 获取触发事件目标元素
// console.log(e.target)
// 判断点击的是删除元素
if (e.target.classList.contains('del')) {
// console.log('点击删除元素')
// 获取图书id(自定义属性id)
const theId = e.target.parentNode.dataset.id
console.log(theId)
// 3.2 调用删除接口
axios({
url: `http://hmajax.itheima.net/api/books/${theId}`,
method:'DELETE'
}).then(() => {
//3.3 刷新图书列表
getBooksList()
})
}
})
4.编辑图书
/**
* 目标4: 编辑图书
* 4.1 编辑弹框 -> 显示和隐藏
* 4.2 获取当前编辑图书数据 -> 回显到编辑表单中
* 4.3 提交保存修改,并刷新列表
*/
// 4.1 编辑弹框 -> 显示和隐藏
const editDom = document.querySelector('.edit-modal')
const editModal = new bootstrap.Modal(editDom)
//编辑元素 -> 点击 -> 弹框显示
document.querySelector('.list').addEventListener('click', e => {
// 判断点击的是否为编辑元素
if (e.target.classList.contains('edit')) {
// 4.2 获取当前编辑图书数据 -> 回显到编辑表单中
const theId = e.target.parentNode.dataset.id
// console.log(theId)
axios({
url: `http://hmajax.itheima.net/api/books/${theId}`
}).then(result => {
// console.log(result)
const bookObj = result.data.data
// document.querySelector('.edit-form .bookname').value = bookObj.bookname
// document.querySelector('.edit-form .author').value = bookObj.author
// 数据对象“属性”和标签“类名”一致
// 遍历数据对象,使用属性去获取对于的标签,快速赋值
const keys = Object.keys(bookObj) // ['id','bookname','author','publisher']
// console.log(keys)
keys.forEach(key => {
document.querySelector(`.edit-form .${key}`).value = bookObj[key]
})
})
editModal.show()
}
})
// 修改按钮 -> 点击 -> 隐藏弹框
document.querySelector('.edit-btn').addEventListener('click', () => {
// 4.3 提交保存修改,并刷新列表
const editForm = document.querySelector('.edit-form')
const {id, bookname, author, publisher} = serialize(editForm, { hash: true, empty: true})
// console.log(bookObj)
// 保存正在编辑的图书id,隐藏起来,无需让用户修改
//<input type="hidden" class="id" name="id" value="385168">
axios({
url: `http://hmajax.itheima.net/api/books/${id}`,
method: 'PUT',
data: {
bookname,
author,
publisher,
creator
}
}).then(() => {
// 修改成功以后,重新获取并刷新列表
getBooksList()
// 隐藏弹框
editModal.hide()
})
})
index.html代码
<!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>
<!-- 字体图标 -->
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3736758_vxpb728fcyh.css">
<!-- 引入bootstrap.css -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
<!-- 核心样式 -->
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 主体区域 -->
<div class="container">
<!-- 头部标题和添加按钮 -->
<div class="top">
<h3>图书管理</h3>
<button type="button" class="btn btn-primary plus-btn" data-bs-toggle="modal" data-bs-target=".add-modal"> + 添加
</button>
</div>
<!-- 数据列表 -->
<table class="table">
<thead class="table-light">
<tr>
<th style="width: 150px;">序号</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th style="width: 180px;">操作</th>
</tr>
</thead>
<tbody class="list">
<tr>
<td>1</td>
<td>JavaScript程序设计</td>
<td>马特·弗里斯比</td>
<td>人民邮电出版社</td>
<td>
<span class="del">删除</span>
<span class="edit">编辑</span>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 新增-弹出框 -->
<div class="modal fade add-modal">
<!-- 中间白色区域 -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header top">
<span>添加图书</span>
<button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body form-wrap">
<!-- 新增表单 -->
<form class="add-form">
<div class="mb-3">
<label for="bookname" class="form-label">书名</label>
<input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
</div>
<div class="mb-3">
<label for="author" class="form-label">作者</label>
<input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="form-label">出版社</label>
<input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
</div>
</form>
</div>
<div class="modal-footer btn-group">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 </button>
<button type="button" class="btn btn-primary add-btn"> 保存 </button>
</div>
</div>
</div>
</div>
<!-- 编辑-弹出框 -->
<div class="modal fade edit-modal">
<!-- 中间白色区域 -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header top">
<span>编辑图书</span>
<button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body form-wrap">
<!-- 编辑表单 -->
<form class="edit-form">
<input type="hidden" class="id" name="id">
<div class="mb-3">
<label for="bookname" class="form-label">书名</label>
<input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
</div>
<div class="mb-3">
<label for="author" class="form-label">作者</label>
<input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="form-label">出版社</label>
<input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
</div>
</form>
</div>
<div class="modal-footer btn-group">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 </button>
<button type="button" class="btn btn-primary edit-btn"> 修改 </button>
</div>
</div>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script src="./lib/form-serialize.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.js"></script>
<!-- 核心逻辑 -->
<script src="./js/index.js"></script>
</body>
</html>
index.css
/* 公共*/
html,
body {
width: 100%;
height: 100%;
}
.container {
width: 1340px;
margin: 0 auto;
padding-top: 60px;
box-sizing: border-box;
}
/* alert提示框 */
.toast {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
}
.toast .toast-body {
padding: 0 !important;
}
.toast .alert-success {
margin-bottom: 0 !important;
}
/* 头部导航 */
.container .top {
display: flex;
justify-content: space-between;
}
.container .top h3 {
font-weight: 900;
}
.container .top .plus-btn {
background-color: #539ACB !important;
color: #fff;
border: none;
}
/* 表格部分 */
.table {
margin-top: 20px;
text-align: center;
font-size: 14px;
}
.table-light th {
background-color: #939CA7 !important;
color: #ffffff;
font-family: PingFangSC-Medium;
font-size: 16px;
text-align: center;
font-weight: 500;
border-right: 1px solid lightgray;
}
.table-light th:last-of-type {
border-right: none;
}
/* 表格内容 */
.table tbody td {
color: #696F77;
}
.table .del {
color: #E5964C;
margin-right: 30px;
}
.table .edit {
color: #539ACB;
}
.table tbody tr {
height: 30px;
line-height: 30px;
}
.table tbody tr td:last-of-type span {
cursor: pointer;
}
/* 弹出层 */
.modal .top {
display: flex;
justify-content: center;
background-color: #F0F3F7;
padding: 15px 0;
width: 100%;
position: relative;
color: #1E2023;
}
/* 右上角-关闭按钮 */
.modal .btn-close {
font-size: 12px;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 23px;
/* 覆盖bootstrap样式 */
margin: 0;
padding: 0;
}
/* 表单容器 */
.form-wrap {
box-sizing: border-box;
background-color: white;
padding: 40px;
}
.form-wrap .form-label {
color: #696F77;
}
/* 修改输入框默认占位文字
webkit内核, firefox18-, firfox19+, 其他
*/
.form-wrap input::-webkit-input-placeholder {
color: #BFBFBF !important;
font-size: 14px;
}
/* 底部按钮组 */
.modal-footer{
border-top: 0;
}
.btn-group {
text-align: center;
width: 100%;
}
/* 修改bs的按钮弹性布局-改成自己设置大小 */
.btn-group,
.btn-group-vertical {
display: block;
}
.btn-group button {
width: 120px
}
.btn-group button:first-of-type {
border: 1px solid #E3E3E3;
background-color: #fff;
color: black;
margin-right: 60px;
}
.btn-group button:last-of-type {
background-color: #539ACB;
}
.alert-success {
border-color: transparent;
}
.toast {
border: none;
}