AJAX——图书管理案例

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.新增图书

javascript 复制代码
/**
 * 目标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.删除图书

javascript 复制代码
/**
 * 目标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.编辑图书

javascript 复制代码
/**
 * 目标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代码

javascript 复制代码
<!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;
}
相关推荐
GISer_Jing2 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪3 小时前
CSS复习
前端·css
咖啡の猫5 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5818 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路8 小时前
GeoTools 读取影像元数据
前端
ssshooter9 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友9 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal10 小时前
关于RSA和AES加密
前端·vue.js