• 前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(二)


    阳光总在风雨后,请相信有彩虹。

    案例 - 图书管理

    bootstrap弹框

    需求,点击添加按钮,没有离开当前页面,在当前页面弹出弹框(弹窗)

    先学着实现一个简单的弹框,如下图右下角

    bootstrap有两种方式控制弹框的显示和隐藏

    ①(自定义)属性控制方式

    1.引入bootstrap.css和bootstrap.js

    并准备好显示弹框的按钮

    2.准备弹框标签,确认结构

    来到bootstrap文档,搜索modal(情态的、模式的)

    Modal模态框

    Bootstrap 模态框(Modal)插件的基本应用-Web前端开发资源网

    点击复制,获取结构

    复制过来后,到网页看,发现并没有出现弹框,查看样式发现有

    display: none;

    display属性属于modal类

    且默认隐藏

    弹框整体结构

    如何实现显示弹框?——bootstrap内部已经提供一些控制显示和隐藏的(自定义)属性

    两个属性,分别是 data-bs-toggledata-bs-target

    data-bs-toggle="modal" :点击会出来一个modal弹框(注意:不是.modal类选择器)

    data-bs-target="css选择器":一个网页里面可能会有多个弹框,需要传入 某个需要点击弹出的弹框的css选择器。

    实操如下

    控制隐藏

    可在弹框头部的×号button元素看到,结构已经携带该属性

    data-bs-dismiss="modal"

    默认×号可关闭弹窗

    删除该属性则×号关闭失效

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Bootstrap 弹框title>
    8. <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
    9. head>
    10. <body>
    11. <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target=".my-box">
    12. 显示弹框
    13. button>
    14. <div class="modal my-box" tabindex="-1">
    15. <div class="modal-dialog">
    16. <div class="modal-content">
    17. <div class="modal-header">
    18. <h5 class="modal-title">Modal titleh5>
    19. <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">button>
    20. div>
    21. <div class="modal-body">
    22. <p>Modal body text goes here.p>
    23. div>
    24. <div class="modal-footer">
    25. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Closebutton>
    26. <button type="button" class="btn btn-primary">Save changesbutton>
    27. div>
    28. div>
    29. div>
    30. div>
    31. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js">script>
    32. body>
    33. html>

    ② JS控制方式

    用属性控制不好吗,不够吗?

    使用属性控制,在显示和隐藏时无法执行其他额外的JS逻辑

    以下代码可以控制弹框的显示和隐藏

    实操代码:

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Bootstrap 弹框title>
    8. <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
    9. head>
    10. <body>
    11. <button type="button" class="btn btn-primary edit-btn">
    12. 编辑姓名
    13. button>
    14. <div class="modal name-box" tabindex="-1">
    15. <div class="modal-dialog">
    16. <div class="modal-content">
    17. <div class="modal-header">
    18. <h5 class="modal-title">请输入姓名h5>
    19. <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">button>
    20. div>
    21. <div class="modal-body">
    22. <form action="">
    23. <span>姓名:span>
    24. <input type="text" class="username">
    25. form>
    26. div>
    27. <div class="modal-footer">
    28. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消button>
    29. <button type="button" class="btn btn-primary save-btn">保存button>
    30. div>
    31. div>
    32. div>
    33. div>
    34. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js">script>
    35. <script>
    36. // 1. 创建弹框对象
    37. const modalDom = document.querySelector('.name-box')
    38. const modal = new bootstrap.Modal(modalDom)
    39. // 编辑姓名->点击->赋予默认姓名->弹框显示
    40. document.querySelector('.edit-btn').addEventListener('click', () => {
    41. document.querySelector('.username').value = '默认姓名'
    42. // 2. 显示弹框
    43. modal.show()
    44. })
    45. // 保存->点击->->获取姓名打印->弹框隐藏
    46. document.querySelector('.save-btn').addEventListener('click', () => {
    47. const username = document.querySelector('.username').value
    48. console.log('模拟把姓名保存到服务器上', username)
    49. // 2. 隐藏弹框
    50. modal.hide()
    51. })
    52. script>
    53. body>
    54. html>

    图书管理案例样式

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>案例-图书管理title>
    8. <link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3736758_vxpb728fcyh.css">
    9. <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
    10. <link rel="stylesheet" href="./css/index.css">
    11. head>
    12. <body>
    13. <div class="container">
    14. <div class="top">
    15. <h3>图书管理h3>
    16. <button type="button" class="btn btn-primary plus-btn" data-bs-toggle="modal" data-bs-target=".add-modal"> + 添加
    17. button>
    18. div>
    19. <table class="table">
    20. <thead class="table-light">
    21. <tr>
    22. <th style="width: 150px;">序号th>
    23. <th>书名th>
    24. <th>作者th>
    25. <th>出版社th>
    26. <th style="width: 180px;">操作th>
    27. tr>
    28. thead>
    29. <tbody class="list">
    30. <tr>
    31. <td>1td>
    32. <td>JavaScript程序设计td>
    33. <td>马特·弗里斯比td>
    34. <td>人民邮电出版社td>
    35. <td>
    36. <span class="del">删除span>
    37. <span class="edit">编辑span>
    38. td>
    39. tr>
    40. tbody>
    41. table>
    42. div>
    43. <div class="modal fade add-modal">
    44. <div class="modal-dialog">
    45. <div class="modal-content">
    46. <div class="modal-header top">
    47. <span>添加图书span>
    48. <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal">button>
    49. div>
    50. <div class="modal-body form-wrap">
    51. <form class="add-form">
    52. <div class="mb-3">
    53. <label for="bookname" class="form-label">书名label>
    54. <input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
    55. div>
    56. <div class="mb-3">
    57. <label for="author" class="form-label">作者label>
    58. <input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
    59. div>
    60. <div class="mb-3">
    61. <label for="publisher" class="form-label">出版社label>
    62. <input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
    63. div>
    64. form>
    65. div>
    66. <div class="modal-footer btn-group">
    67. <button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 button>
    68. <button type="button" class="btn btn-primary add-btn"> 保存 button>
    69. div>
    70. div>
    71. div>
    72. div>
    73. <div class="modal fade edit-modal">
    74. <div class="modal-dialog">
    75. <div class="modal-content">
    76. <div class="modal-header top">
    77. <span>编辑图书span>
    78. <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal">button>
    79. div>
    80. <div class="modal-body form-wrap">
    81. <form class="edit-form">
    82. <input type="hidden" class="id" name="id">
    83. <div class="mb-3">
    84. <label for="bookname" class="form-label">书名label>
    85. <input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
    86. div>
    87. <div class="mb-3">
    88. <label for="author" class="form-label">作者label>
    89. <input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
    90. div>
    91. <div class="mb-3">
    92. <label for="publisher" class="form-label">出版社label>
    93. <input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
    94. div>
    95. form>
    96. div>
    97. <div class="modal-footer btn-group">
    98. <button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 button>
    99. <button type="button" class="btn btn-primary edit-btn"> 修改 button>
    100. div>
    101. div>
    102. div>
    103. div>
    104. <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js">script>
    105. <script src="./lib/form-serialize.js">script>
    106. <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.js">script>
    107. <script src="./js/index.js">script>
    108. body>
    109. html>

    渲染列表

    引入相关css文件

    相关js文件

    根据接口文档,书写axios获取数据

    再渲染数据

    新增图书

    新增图书核心代码:

    1. /**
    2. * 目标2:新增图书
    3. * 2.1 新增弹框->显示和隐藏
    4. * 2.2 收集表单数据,并提交到服务器保存
    5. * 2.3 刷新图书列表
    6. */
    7. // 2.1 创建弹框对象
    8. const addModalDom = document.querySelector('.add-modal')
    9. const addModal = new bootstrap.Modal(addModalDom)
    10. // 保存按钮->点击->隐藏弹框
    11. document.querySelector('.add-btn').addEventListener('click', () => {
    12. // 2.2 收集表单数据,并提交到服务器保存
    13. const addForm = document.querySelector('.add-form')
    14. const bookObj = serialize(addForm, { hash: true, empty: true })
    15. // console.log(bookObj)
    16. // 提交到服务器
    17. axios({
    18. url: 'http://hmajax.itheima.net/api/books',
    19. method: 'POST',
    20. data: {
    21. ...bookObj,
    22. creator
    23. }
    24. }).then(result => {
    25. // console.log(result)
    26. // 2.3 添加成功后,重新请求并渲染图书列表
    27. getBooksList()
    28. // 重置表单
    29. addForm.reset()
    30. // 隐藏弹框
    31. addModal.hide()
    32. })
    33. })

    删除图书

    1. /**
    2. * 目标3:删除图书
    3. * 3.1 删除元素绑定点击事件->获取图书id
    4. * 3.2 调用删除接口
    5. * 3.3 刷新图书列表
    6. */
    7. // 3.1 删除元素->点击(事件委托)
    8. document.querySelector('.list').addEventListener('click', e => {
    9. // 获取触发事件目标元素
    10. // console.log(e.target)
    11. // 判断点击的是删除元素
    12. if (e.target.classList.contains('del')) {
    13. // console.log('点击删除元素')
    14. // 获取图书id(自定义属性id)
    15. const theId = e.target.parentNode.dataset.id
    16. // console.log(theId)
    17. // 3.2 调用删除接口
    18. axios({
    19. url: `http://hmajax.itheima.net/api/books/${theId}`,
    20. method: 'DELETE'
    21. }).then(() => {
    22. // 3.3 刷新图书列表
    23. getBooksList()
    24. })
    25. }
    26. })

    本次调用删除接口,需要在path路径上传参,method为delete

    发送axios完成图书删除后,别忘了刷新列表(在then中刷新)

    编辑图书

    回显图书信息

    需要用到的接口,查询图书详情接口,显示到编辑弹框里。

    查询到的数据对象的属性名和 标签的类名 一致

    我们可以遍历数据对象,使用属性去获取对应的标签,快速赋值

    提交修改时,获取修改信息

    观察表单,为什么会出现id?

    存在隐藏的表单域id

    可以不写吗?为什么隐藏?

    ——需要提交修改,需要携带图书id

    ——不能让用户看见,不然用户可以修改

    因为存在id表单域,可被serialize收集到

    使用修改图书详情接口,

    先把serialize获取到的表单数据(对象)解构出来,再放入请求体,

    前面已经定义好了外号creator

    编辑图书核心代码:

    1. /**
    2. * 目标4:编辑图书
    3. * 4.1 编辑弹框->显示和隐藏
    4. * 4.2 获取当前编辑图书数据->回显到编辑表单中
    5. * 4.3 提交保存修改,并刷新列表
    6. */
    7. // 4.1 编辑弹框->显示和隐藏
    8. const editDom = document.querySelector('.edit-modal')
    9. const editModal = new bootstrap.Modal(editDom)
    10. // 编辑元素->点击->弹框显示
    11. document.querySelector('.list').addEventListener('click', e => {
    12. // 判断点击的是否为编辑元素
    13. if (e.target.classList.contains('edit')) {
    14. // 4.2 获取当前编辑图书数据->回显到编辑表单中
    15. const theId = e.target.parentNode.dataset.id
    16. axios({
    17. url: `http://hmajax.itheima.net/api/books/${theId}`
    18. }).then(result => {
    19. const bookObj = result.data.data
    20. // document.querySelector('.edit-form .bookname').value = bookObj.bookname
    21. // document.querySelector('.edit-form .author').value = bookObj.author
    22. // 数据对象“属性”和标签“类名”一致
    23. // 遍历数据对象,使用属性去获取对应的标签,快速赋值
    24. const keys = Object.keys(bookObj) // ['id', 'bookname', 'author', 'publisher']
    25. keys.forEach(key => {
    26. document.querySelector(`.edit-form .${key}`).value = bookObj[key]
    27. })
    28. })
    29. editModal.show()
    30. }
    31. })
    32. // 修改按钮->点击->隐藏弹框
    33. document.querySelector('.edit-btn').addEventListener('click', () => {
    34. // 4.3 提交保存修改,并刷新列表
    35. const editForm = document.querySelector('.edit-form')
    36. const { id, bookname, author, publisher } = serialize(editForm, { hash: true, empty: true})
    37. // 保存正在编辑的图书id,隐藏起来:无需让用户修改
    38. //
    39. axios({
    40. url: `http://hmajax.itheima.net/api/books/${id}`,
    41. method: 'PUT',
    42. data: {
    43. bookname,
    44. author,
    45. publisher,
    46. creator
    47. }
    48. }).then(() => {
    49. // 修改成功以后,重新获取并刷新列表
    50. getBooksList()
    51. // 隐藏弹框
    52. editModal.hide()
    53. })
    54. })

    总结——增删改查

    图片上传

    上传图片接口请求体所需数据类型不再是application-json而是form-data

    为文件类型,图片文件file不能直接转成json格式。

    使用input元素(type="file")供用户选择上传文件,

    使用change监听事件,

    通过e.target获取表单元素,

    通过files属性获得一个文件伪数组,

    打印文件对象:

    使用FormData携带图片文件,

    根据接口文档在axios中传入数据:

    选择图片并发送axios请求,

    到控制台查看本次请求,

    点击请求,打开载荷,

    图片文件浏览器进行了格式化(二进制)

    再看到服务器的响应,已返回图片地址

    使用图片地址,展示图片

    案例 - 网站换肤

    使用label标签(样式容易修改)的for属性关联input标签的id

    设置成功后进行本地存储,注意,每次打开页面时需要判断,

    本地存有背景图地址才进行设置(使用逻辑与的短路特性):

    但逻辑与的运算符优先级高于赋值运算符,需要添加小括号

    gbUrl && (document.body.style.backgroundImage = `url(${bgUrl})`)

    实操代码:

    1. /**
    2. * 目标:网站-更换背景
    3. * 1. 选择图片上传,设置body背景
    4. * 2. 上传成功时,"保存"图片url网址
    5. * 3. 网页运行后,"获取"url网址使用
    6. * */
    7. document.querySelector('.bg-ipt').addEventListener('change', e => {
    8. // 1. 选择图片上传,设置body背景
    9. console.log(e.target.files[0])
    10. const fd = new FormData()
    11. fd.append('img', e.target.files[0])
    12. axios({
    13. url: 'http://hmajax.itheima.net/api/uploadimg',
    14. method: 'POST',
    15. data: fd
    16. }).then(result => {
    17. const imgUrl = result.data.data.url
    18. document.body.style.backgroundImage = `url(${imgUrl})`
    19. // 2. 上传成功时,"保存"图片url网址
    20. localStorage.setItem('bgImg', imgUrl)
    21. })
    22. })
    23. // 3. 网页运行后,"获取"url网址使用
    24. const bgUrl = localStorage.getItem('bgImg')
    25. console.log(bgUrl)
    26. bgUrl && (document.body.style.backgroundImage = `url(${bgUrl})`)

    案例 - 个人信息设置

    1.信息渲染

    1. /**
    2. * 目标1:信息渲染
    3. * 1.1 获取用户的数据
    4. * 1.2 回显数据到标签上
    5. * */
    6. const creator = '播仔'
    7. // 1.1 获取用户的数据
    8. axios({
    9. url: 'http://hmajax.itheima.net/api/settings',
    10. params: {
    11. creator
    12. }
    13. }).then(result => {
    14. const userObj = result.data.data
    15. // 1.2 回显数据到标签上
    16. Object.keys(userObj).forEach(key => {
    17. if (key === 'avatar') {
    18. // 赋予默认头像
    19. document.querySelector('.prew').src = userObj[key]
    20. } else if (key === 'gender') {
    21. // 赋予默认性别
    22. // 获取性别单选框:[男radio元素,女radio元素]
    23. const gRadioList = document.querySelectorAll('.gender')
    24. // 获取性别数字:0男,1女
    25. const gNum = userObj[key]
    26. // 通过性别数字,作为下标,找到对应性别单选框,设置选中状态
    27. gRadioList[gNum].checked = true
    28. } else {
    29. // 赋予默认内容
    30. document.querySelector(`.${key}`).value = userObj[key]
    31. }
    32. })
    33. })

    2.头像修改

    1. /**
    2. * 目标2:修改头像
    3. * 2.1 获取头像文件
    4. * 2.2 提交服务器并更新头像
    5. * */
    6. // 文件选择元素->change事件
    7. document.querySelector('.upload').addEventListener('change', e => {
    8. // 2.1 获取头像文件
    9. console.log(e.target.files[0])
    10. const fd = new FormData()
    11. fd.append('avatar', e.target.files[0])
    12. fd.append('creator', creator)
    13. // 2.2 提交服务器并更新头像
    14. axios({
    15. url: 'http://hmajax.itheima.net/api/avatar',
    16. method: 'PUT',
    17. data: fd
    18. }).then(result => {
    19. const imgUrl = result.data.data.avatar
    20. // 把新的头像回显到页面上
    21. document.querySelector('.prew').src = imgUrl
    22. })
    23. })

    3.信息修改

    4.提示框

    模态框使用方法相似

    提示框结构

    核心JS代码

    1. /**
    2. * 目标3:提交表单
    3. * 3.1 收集表单信息
    4. * 3.2 提交到服务器保存
    5. */
    6. /**
    7. * 目标4:结果提示
    8. * 4.1 创建toast对象
    9. * 4.2 调用show方法->显示提示框
    10. */
    11. // 保存修改->点击
    12. document.querySelector('.submit').addEventListener('click', () => {
    13. // 3.1 收集表单信息
    14. const userForm = document.querySelector('.user-form')
    15. const userObj = serialize(userForm, { hash: true, empty: true })
    16. userObj.creator = creator
    17. // 性别数字字符串,转成数字类型
    18. userObj.gender = +userObj.gender
    19. console.log(userObj)
    20. // 3.2 提交到服务器保存
    21. axios({
    22. url: 'http://hmajax.itheima.net/api/settings',
    23. method: 'PUT',
    24. data: userObj
    25. }).then(result => {
    26. // 4.1 创建toast对象
    27. const toastDom = document.querySelector('.my-toast')
    28. const toast = new bootstrap.Toast(toastDom)
    29. // 4.2 调用show方法->显示提示框
    30. toast.show()
    31. })
    32. })

    HTML文件

    1. html>
    2. <html lang="zh-CN">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
    8. <link rel="stylesheet" href="./css/index.css">
    9. <title>个人信息设置title>
    10. head>
    11. <body>
    12. <div class="toast my-toast" data-bs-delay="1500">
    13. <div class="toast-body">
    14. <div class="alert alert-success info-box">
    15. 操作成功
    16. div>
    17. div>
    18. div>
    19. <div class="container">
    20. <ul class="my-nav">
    21. <li class="active">基本设置li>
    22. <li>安全设置li>
    23. <li>账号绑定li>
    24. <li>新消息通知li>
    25. ul>
    26. <div class="content">
    27. <div class="info-wrap">
    28. <h3 class="title">基本设置h3>
    29. <form class="user-form" action="javascript:;">
    30. <div class="form-item">
    31. <label for="email">邮箱label>
    32. <input id="email" name="email" class="email" type="text" placeholder="请输入邮箱" autocomplete="off">
    33. div>
    34. <div class="form-item">
    35. <label for="nickname">昵称label>
    36. <input id="nickname" name="nickname" class="nickname" type="text" placeholder="请输入昵称" autocomplete="off">
    37. div>
    38. <div class="form-item">
    39. <label>性别label>
    40. <label class="male-label"><input type="radio" name="gender" class="gender" value="0">label>
    41. <label class="male-label"><input type="radio" name="gender" class="gender" value="1">label>
    42. div>
    43. <div class="form-item">
    44. <label for="desc">个人简介label>
    45. <textarea id="desc" name="desc" class="desc" placeholder="请输入个人简介" cols="20" rows="10" autocomplete="off">textarea>
    46. div>
    47. <button class="submit">提交button>
    48. form>
    49. div>
    50. <div class="avatar-box">
    51. <h4 class="avatar-title">头像h3>
    52. <img class="prew" src="./img/头像.png" alt="">
    53. <label for="upload">更换头像label>
    54. <input id="upload" type="file" class="upload">
    55. div>
    56. div>
    57. div>
    58. <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js">script>
    59. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js">script>
    60. <script src="./lib/form-serialize.js">script>
    61. <script src="./js/index.js">script>
    62. body>
    63. html>

  • 相关阅读:
    Java:ApacheHttpClient连接寿命(timeToLive)未配置问题分析
    2.4GHz无线MCU芯片:CSM2433芯片 亿胜盈科
    KKVIEW远程控制: 远程控制APP下载
    【Asp】调试Asp,用alert弹出变量值的值和写入txt文件
    oracle数据库导出数据为csv包含clob数据
    前端知识整理(1-5)
    复杂查询方法-视图、子查询、函数等
    ShardingSphere-proxy-5.0.0建立mysql读写分离的连接(六)
    BiSeNet v2
    python基于PHP+MySQL的连锁商店仓库管理系统
  • 原文地址:https://blog.csdn.net/upgrade_bro/article/details/133858044