综合案例 --- 图书管理(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()
            }

        })
})
posted @ 2024-05-26 16:38  河图s  阅读(16)  评论(0编辑  收藏  举报