Ajax_02
01_Bootstrap框架-控制弹框的使用
代码
<!-- 引入bootstrap.css --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"><button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target=".my-box">显示弹框 </button><!-- 弹框代码 --> <div class="modal my-box" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">Modal title</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div><div class="modal-body"><p>Modal body text goes here.</p></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button><button type="button" class="btn btn-primary">Save changes</button></div></div></div> </div><!-- 引入bootstrap.js --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script>
- 通过自定义属性,控制弹框的显示和隐藏.自己能够控制属性,从而进行更改
02_通过js方式控制弹框
目标:使用JS控制弹框,显示和隐藏
-
创建弹框对象
-
调用弹框对象内置方法
.show() 显示
.hide() 隐藏
代码示例
<!-- 引入bootstrap.css --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"><button type="button" class="btn btn-primary edit-btn">编辑姓名 </button><div class="modal name-box" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">请输入姓名</h5><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div><div class="modal-body"><form action=""><span>姓名:</span><input type="text" class="username"></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><!-- 引入bootstrap.js --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js"></script><script>// 1、创建弹框对象const modalDom = document.querySelector('.name-box')const modal = new bootstrap.Modal(modalDom)// 编辑姓名 -> 点击 -> 赋予一个默认的姓名 -> 弹框显示document.querySelector('.edit-btn').addEventListener('click', () => {document.querySelector('.username').value = '默认姓名'// 2、显示弹框modal.show()})// 保存 -> 点击 -> 获取姓名打印 -> 弹框隐藏document.querySelector('.save-btn').addEventListener('click', () => {const username = document.querySelector('.username').valueconsole.log('模拟把姓名保存到服务器上',username)// 3、隐藏弹框modal.hide()})</script>
- 关于这两种方式控制弹框的显示和隐藏,至于怎么选择,我们取决于业务逻辑,如果只是单纯的控制显示和隐藏,那么直接使用bootstrap属性控制即可,反正就得使用js控制
图书管理业务
需求: 对服务器的图书数据进行 增、删、改、查。功能的实现,同时实时动态的渲染刷新页面内容
根据功能模块分为四个业务模块,下面有各个业务的实现步骤
01_ 渲染图书列表业务
* 目标1:渲染图书列表
* 1.1 获取数据
* 1.2 渲染数据
业务1代码
// 固定的携带参数别名 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.dataconsole.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()
02_新增图书业务
目标2:新增图书
* 2.1 新增弹框 -> 显示和隐藏
* 2.2 收集表单数据,并提交给服务器
* 2.3 刷新图书列表、同时重置表单
业务2代码
// 2.1 创建一个弹框对象 const addModalDom = document.querySelector('.add-modal') const addModal = new bootstrap.Modal(addModalDom) // 给保存按钮添加点击事件 document.querySelector('.add-btn').addEventListener('click', () => {// 2.2 收集表单数据,并提交给服务器const form = document.querySelector('.add-form')// 使用serialize插件的函数获取拥有anme属性的表单值const data = serialize(form, { hash: true, empty: true })// 使用对象解构对获取的值进行处理,用于提交数据const { bookname, author, publisher } = dataconsole.log(data)// 2.2.1 向服务器发送提交请求(提交到服务器)axios({url: 'http://hmajax.itheima.net/api/books',method: 'post',data: {...data,creator}}).then(result => {console.log(result)// 2.3 服务器响应后我们需要重新渲染图书数据列表getBooksList()// 重置表单form.reset()// 隐藏弹框addModal.hide()}) })
这里的显示,我们使用bootstrap属性控制就可以了,但是隐藏我们需要提交数据,所以我们使用js来控制。
03_删除图书业务
* 目标3: 删除图书
* 3.1 删除元素绑定点击事件 -> 获取图书id
* 3.2 调用删除接口
* 3.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.idconsole.log(theId)// 3.2 调用删除接口axios({// 使用模板字符串 路径传参url: `http://hmajax.itheima.net/api/books/${theId}`,method: 'DELETE'}).then(result => {// 3.3 刷新图书列表getBooksList()console.log(result)}).catch(error => {console.log(error)console.log(error.response.data.message)})} })
04_编辑图书业务
* 目标4 :编辑图书
* 4.1 编辑弹框 -> 显示和隐藏
* 4.2 获取当前编辑图书数据 -> 回显到编辑表单中
* 4.3 提交保存修改 ,并刷新列表
业务4代码
// 4.1 编辑弹框 -> 显示和隐藏 (使用js方式控制) const editDom = document.querySelector('.edit-modal') // 通过bootstrap.Modal构造函数创建一个实例对象 const editModal = new bootstrap.Modal(editDom) // 给编辑元素 -> 绑定 ->委托事件 document.querySelector('.list').addEventListener('click', e => {// 判断点击的是否为 edit 这个类 的标签if (e.target.classList.contains('edit')) {// console.log('编辑')// 4.2 获取当前编辑图书数据 -> 回显到编辑表单中const theId = e.target.parentNode.dataset.id// console.log(theId)axios({// 路径传参 嵌入进去url: `http://hmajax.itheima.net/api/books/${theId}`,method: 'GET',}).then(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']keys.forEach(key => {document.querySelector(`.edit-form .${key}`).value = bookObj[key]})})// 给弹框对象添加show方法,让编辑框显示出来editModal.show()} })// 修改按钮 -> 点击 -> 隐藏按钮 document.querySelector('.edit-btn').addEventListener('click', () => {// 4.3 提交保存修改 ,并刷新列表const editForm = document.querySelector('.edit-form')const bookObj = serialize(editForm ,{ hash: true ,empty: true })// 下面是保存正在编辑的图书id ,隐藏起来:无需让用户修改// <input type="hidden" class="id" name="id" value="228500">axios({url: `http://hmajax.itheima.net/api/books/${bookObj.id}`,method: 'PUT',data: {...bookObj,creator}}).then(() => {// 修改成功以后,重新获取并刷新列表getBooksList()// 隐藏弹框editModal.hide()})})
业务总结
- 核心的步骤
* 业务1:渲染图书列表
* 1.1 获取数据
* 1.2 渲染数据
业务2:新增图书
* 2.1 新增弹框 -> 显示和隐藏
* 2.2 收集表单数据,并提交给服务器
* 2.3 刷新图书列表、同时重置表单
* 业务3: 删除图书
* 3.1 删除元素绑定点击事件 -> 获取图书id
* 3.2 调用删除接口
* 3.3 刷新图书列表
* 业务4 :编辑图书
- 显示和隐藏
* 4.2 获取当前编辑图书数据 -> 回显到编辑表单中
* 4.3 提交保存修改 ,并刷新列表
在所有的查询和请求中,只要服务器的数据发生变化,同时也需要渲染刷新页面的内容.
图片上传
上传-图片
注意1:上传的图片必须在2MB以内
注意2:服务器端oss(阿里云对象存储)为了安全性,图片url网址不能直接在浏览器地址栏访问
请用img/背景图方式进行使用
* 目标:图片上传,显示到网页上
* 1. 获取图片文件
* 2. 使用 FormData 携带图片文件
* 3. 提交到服务器,获取图片url网址使用
代码示例
// 1.获取选择文件按钮,同时注册一个变化事件document.querySelector('.upload').addEventListener('change', e => {console.log(e.target.files[0])// 2. 使用 FormData 构造函数 携带图片文件夹const imgs = new FormData()// 调用实例对象中 append 方法,传入图片imgs.append('img',e.target.files[0])// 3. 提交到服务器,获取图片url网址使用axios({url: 'http://hmajax.itheima.net/api/uploadimg',method: 'POST',data: imgs}).then(result => {console.log(result.data.data)const imgUrl = result.data.data.urldocument.querySelector('.my-img').src = imgUrl})})
携带的参数具体需要参考接口文档。
网站背景更换
- 目标:网站-更换背景
- 选择图片上传,设置body背景
- 上传成功时,"保存"图片url网址
- 网页运行后,"获取"url网址使用
代码示例
//1、选择图片上传,给body设置背景图片 // 1.2 获取按钮进行上传 document.querySelector('.bg-ipt').addEventListener('change', e => {console.log(e.target.files[0])// 表单事件对象const fd = new FormData()fd.append('img' , e.target.files[0])axios({url: 'http://hmajax.itheima.net/api/uploadimg',method: 'POST',data: fd}).then(result => {const res = result.data.data.url// 更换body的背景图document.body.style.backgroundImage = `url(${res})`// 2、上传成功时,"保存"图片url网址 到本地,防止刷新丢失localStorage.setItem('bgImg',res)}) })// 3. 网页运行后,"获取"url网址使用 const bgUrl = localStorage.getItem('bgImg') console.log(bgUrl) // 逻辑与中断,本地有服务器提交后的url的话,那么就执行后面的,否则为空值不执行 bgUrl && (document.body.style.backgroundImage = `url(${bgUrl})`)
- 在上传图片的基础上增加了存储到本地的功能需求,同时没有url返回,不执行更换背景。
个人信息业务
01_信息渲染
* 目标1:信息渲染
* 1.1 获取用户的数据
* 1.2 回显数据到标签上
模块一代码
// 业务1、信息渲染// 1.1 获取用户的数据 const creator = 'cv爱好者' axios({url: 'http://hmajax.itheima.net/api/settings',method: 'GET',params: {creator} }).then(result => {const userObj = result.data.dataconsole.log(userObj)// 1.2 回显数据到标签上const user = Object.keys(userObj)user.forEach(item => {if (item === 'avatar') {// 单独赋予默认头像document.querySelector('.prew').src = userObj[item]} else if (item === 'gender') {// 单独赋予默认性别 [男radio元素 ,女radio元素]const getGender = document.querySelectorAll('.gender') //获取到伪数组,节点列表// 获取到性别数字; 0 男 1 女const gNum = userObj[item]// 通过性别数字,作为下标,找到对应性别单选框,设置选中状态getGender[gNum].checked = true} else {// 赋予默认内容document.querySelector(`.${item}`).value = userObj[item]}}) })
02_ 头像修改
* 目标2: 头像修改
* 2.1 选择头像文件
* 2.1 提交保存 + 回显
模块二代码
//点击事件 ,上传头像 document.querySelector('.upload').addEventListener('change' ,e => {console.log(e.target.files[0])// 使用表单事件对象 FormData 构造函数 目的就是提交服务器得到url网址const newImg = new FormData()newImg.append('avatar',e.target.files[0])newImg.append('creator',creator)// 2.1 提交保存 + 回显axios({url: 'http://hmajax.itheima.net/api/avatar',method: 'PUT',data: newImg}).then(result => {// 得到图片url网址const imgUrl = result.data.data.avatar// 把头像回显到页面上document.querySelector('.prew').src = imgUrl}) })
03_信息修改_ + 弹框提示
* 目标3 ;信息修改
* 3.1: 收集表单信息
* 3.2: 提交到服务器保存
* 目标4: 提示框显示
* 4.1: 创建toast对象(弹框对象)
* 4.2: 调用show方法 -> 显示提示框
模块三 + 模块四 代码示例
// 注册事件 document.querySelector('.submit').addEventListener('click', () => {const form = document.querySelector('.user-form')// 使用serialize插件获取表单元素const formObj = serialize(form , { hash: true , empty: true})// 添加一个别名属性到收集的表单中formObj.creator = creator// 将性别数字转为 数字型formObj.gender = + formObj.gender// 3.2: 提交到服务器保存axios({url: 'http://hmajax.itheima.net/api/settings',method: 'PUT',data: formObj}).then(result => {// 4.1: 创建toast对象(弹框对象)const toastDom = document.querySelector('.my-toast')const toast = new bootstrap.Toast(toastDom)// 4.2: 调用show方法 -> 显示提示框toast.show()}) })
有几个经典的处理数据的方式,将会再改文章后进行单独补充。也希望自己能够坚持的重复的掌握好学习过的知识技术方式,不断地积累。