以下笔记均为学习哔站黑马程序员AJAX视频所得!!!
AJAX作用:浏览器和服务器之间通信,动态数据交互
axios函数
先引入axios库,可在bootcdn中寻找相关js文件或者对应的script标签
axios({url:'http://hmajax.itheima.net/api/provice'//获取数据的地址}).then(result=>{console.log(result)//一个对象console.log(result.data.list)//一个数组console.log(result.data.list.join('<br>'))//将数组中的元素以换行线隔开document.querySelector('p').innerHTML=result.data.list.join('<br>')})
URL
- http协议:超文本传输协议,规定浏览器和服务器之间传输数据的格式
- 域名:标记服务器在互联网中方位(必须)
- 资源路径:标记资源在服务器下的具体位置
axios({url:'http://hmajax.itheima.net/api/city',// 查询参数params:{pname:'辽宁省'//最终只会提取出辽宁省下面的部分,其他省的城市不会出现}}).then(result=>{console.log(result.data.list)document.querySelector('p').innerHTML=result.data.list.join('<br>')})
URL查询参数
定义:浏览器提供给服务的额外信息,让服务器返回浏览器想要的数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
作用:浏览器提供给服务器额外的信息,获取对应的数据
axios-查询参数
语法:使用axios提供的params选项
注意:axios在运行时把参数名和值,会拼接到url?参数名=值
地区查询(从服务器中获取数据)
需求:根据输入的省份名字和城市名字,查询地区并渲染列表
首先:确定URL网址和参数说明
- 查询某个省内某个城市的所有地区:http://hmajax.itheima.net/api/area
- 参数名:
- pname:省份名字或直辖市名字,比如北京,福建省,辽宁省
- cname:城市名字,比如北京市,厦门市,大连市
完整:http://hmajax.itheima.net/api/area?pname=北京&cname=北京市
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
<style>:root {font-size: 15px;}body {padding-top: 15px;}.mb-3 {display: inline-block;}li {list-style: none;}
</style>
</head>
<body><div class="container"><form id="ediForm" class="row"><div class="mb-3 col"><label class="form-lable">省份名字</label><input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名称" ></div><div class="mb-3 col"><label class="form-lable">城市名字</label><input type="text" value="北京市" name="city" class="form-control city" placeholder="请输入城市名称" ></div></form><button type="button" class="btn btn-primary sel-btn">查询</button><br><p>地区列表:</p><ul class="list-group"><!-- 实例地区 --><li class="list-group-item">东城区</li></ul></div><script src="https://cdn.bootcdn.net/ajax/libs/axios/1.6.8/axios.min.js"></script><script>document.querySelector('.sel-btn').addEventListener('click',()=>{// 获取省份和城市名字let pName=document.querySelector('.province').valuelet cName=document.querySelector('.city').value// 基于axios请求地区列表数据axios({url: 'http://hmajax.itheima.net/api/area',params:{pname:pName,cname:cName//pname和cname为后端规定接口,不可随意改变,当要传进去的参数和pname,cname同名时,可以简化,params中只写pname,cname}}).then(result=>{// 把数据转成li标签 插入到页面上let list=result.data.listconsole.log(list)let theLi=list.map(areaName=>`<li class="list-group-item">${areaName}</li>`).join('')document.querySelector('.list-group').innerHTML=theLi})//theLi里面包含了很多个li标签,将其转化为字符串用join})</script>
</body>
</html>
常用请求方法:
请求方法:对服务器资源,要执行的操作
请求方法 | 操作 |
---|---|
GET | 获取数据 |
POST | 提交数据 |
PUT | 修改数据 |
DELETE | 删除数据 |
PATCH | 修改数据(部分) |
数据提交
当数据需要在服务器上保存
axios请求配置
- url:请求的URL地址
- method:请求的方法,GET方法可以省略(不区分大小写)
- data:提交数据
数据提交-注册账号
- 需求:通过axios提交用户名和密码,完成注册功能
- 注册用户URL地址:http://hmajax.itheima.net/api/register
- 请求方法:POST
参数名:
username 用户名(中英文和数字组成,最少8位)
password密码(最少6位)
// 目标:点击按钮,通过axios提交用户和密码,完成注册document.querySelector('.btn').addEventListener('click',()=>{axios({url:'http://hmajax.itheima.net/api/register',// 指定请求方法method:'post',// 提交数据data:{username:'zj05090429',password:'123456'}}).then(result=>{console.log(result)})})
在上述代码中,再次注册相同的账号,会遇到报错信息,提示,账号已被占用
axios错误处理
场景:再次注册相同的账号,会遇到报错处理
处理:用更直观的方式,给普通用户展示错误信息,如下:
语法:在then方法的后面,通过点语法调用catch方法,传入回调函数并定义形参
处理:注册案例,重复注册时通过弹框提示用户错误原因
axios({url:'http://hmajax.itheima.net/api/register',// 指定请求方法method:'post',// 提交数据data:{username:'zj05090429',password:'123456'}}).then(result=>{// 成功console.log(result)}).catch(error=>{// 失败// 处理错误信息// console.log(error)// console.log(error.response.data.message)alert(error.response.data.message)})})
HTTP协议-请求报文
HTTP协议:规定了浏览器发送及服务器返回内容的格式
请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容
请求报文的组成部分有:
1.请求行:请求方法,URL,协议
2.请求头:以键值对的格式携带的附加信息,比如:Content-type
3.空行:分隔请求头,空行之后的是发送给服务器的资源
4.请求体:发送的资源
最终会将传入的数据对象转化为JSON字符串携带到请求报文中
请求报文-错误排查,可通过查看载荷中传入的数据进行分析排查
HTTP协议-响应报文
响应报文:服务器按照HTTP协议要求的格式,返回给浏览器的内容
1.相应行(状态行):协议、HTTP响应状态码、状态信息
2.相应头:以键值对的格式写到的附加信息,比如:Content-Type
3.空行:分隔响应头,空行之后的是服务器返回的资源
4.响应体:返回的资源
HTTP响应状态码:用来表明请求是否成功完成
比如:404(服务器找不到资源)
状态码 | 说明 |
---|---|
1xx | 信息 |
2xx | 成功 |
3xx | 重定向消息 |
4xx | 客户端错误 |
5xx | 服务端错误 |
接口文档
接口文档:描述接口的文章
接口:使用AJAX和服务器通讯时,请求方法,以及参数
axios({url:'http://hmajax.itheima.net/api/login',method:'post',data:{username:'itheima007',password:'7654321'}})})
案例-用户登录
1.点击登录时,判断用户名和密码长度
2.提交数据和服务器通信
3.提示信息
const myAlert=document.querySelector('.alert')// 封装提示框函数,重复调用 满足提示需求// 功能:// 1.显示提示显示框// 2.不同提示文字msg,和成功绿色失败红色 issucess(true成功,false失败)// 3.过两秒之后,让提示框自动消失function alertFn(msg,isSucess){// 显示提示框myAlert.classList.add('show')// 实现细节myAlert.innerText=msgconst bgStyle=isSucess?'alert-sucess':'alert-danger'//boootstrap框架myAlert.classList.add(bgStyle)// 过两秒隐藏setTimeout(()=>{myAlert.classList.remove('show')// 避免类冲突,重置背景色myAlert.classList.remove(bgStyle)},2000)}document.querySelector('.btn-login').addEventListener('cilck',()=>{const username=document.querySelector('.username').valueconst password=document.querySelector('.password').value// 1.3判断长度if(username.length<8){alertFn('用户名必须大于8位',false)console.log('用户名必须大于等于8位')return//组织代码继续执行}if(password.length<6){alertFn('密码必须大于等于6位',false)console.log('密码必须大于等于6位')return//阻止代码继续执行}//基于axios提交用户名和密码console.log('提交数据到服务器')axios({url:'http://hmajax.itheima.net/api/login',method:'POST',data:{username,password}}).then(result=>{// console.log(result)alertFn(result.data.message,true)console.log(result.data.message)}).catch(error=>{console.log(error)console.log(error.response.data.message)//用户名或密码错误})})
form-serialize插件
作用:快速收集表单元素的值
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><form action="javascript:;" class="example-form"><input type="text" name="uname"><br><input type="text" name="pwd"><br><input type="button" value="提交" class="btn"></form><!-- 在点击提交时,使用form-serialize插件,快速收集表单元素值--><script src="./lib/form-serialize.js"></script><script>document.querySelector('.btn').addEventListener('click',()=>{/*** 使用serialize函数,快速收集表单元素的值* 参数1:要获取哪个表单的数据* 表单元素设置name属性 值会作为对象的属性名* 建议name属性的值,最好和接口文档的参数名一致* hash 设置获取数据结构* - true JS对象(true)推荐* - false 获取查询字符串url?后面传递的参数* empty 设置是否获取空值* - true:获取空值 推荐* - false:不获取空值* 参数2:配置对象*/const form=document.querySelector('.example-form')// const data=serialize(form,{hash:true,empty:true})const data=serialize(form,{hash:false,empty:true})console.log(data)})</script>
</body>
</html>
hash:true
hash:false
使用form-serialilze插件获取用户登录中表单里的数据
const form=document.querySelector('.login-form')const data=serialize(form,{hash:true,empty:true})const {username,password}=data//解构赋值// const username = document.querySelector('.username').value// const password = document.querySelector('.password').value// console.log(username, password)
Bootstrap弹框的使用
功能:不离开当前页面,显示单独内容,供用户操作
步骤:
- 引入bootstrap.css和bootstrap.js
- 准备弹框标签,确认结构
- 通过自定义属性,控制弹框的显示和隐藏、
通过属性设置,弹框的显示或隐藏(单纯显示和隐藏)
<!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>Bootstrap 弹框</title><!-- 引入bootstrap.css --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head><body><!-- 目标:使用Bootstrap弹框1. 引入bootstrap.css 和 bootstrap.js2. 准备弹框标签,确认结构3. 通过自定义属性,控制弹框的显示和隐藏--><button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target=".my-box">显示弹框</button><!-- 弹框标签bootstrap的modal弹框,添加modal类名(默认隐藏)--><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>
</body></html>
通过JS设置,弹框显示或隐藏(需要额外逻辑代码)
// 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)// 2. 隐藏弹框modal.hide()})
图书管理
自己的图书数据:给自己起个外号,并告诉服务器,默认会有三本书,基于这三本书做数据的增删改查
渲染图书列表
/*** 目标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.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 data-id=${item.id}><span class="del">删除</span><span class="edit">编辑</span></td></tr>` //映射到数组的每个元素 并返回修改过的新数组}).join('')// console.log(htmlStr)document.querySelector('.list').innerHTML = htmlStr})
}
新增图书
/*** 目标2:新增图书* 2.1 新增弹框->显示和隐藏* 2.2 收集表单数据,并提交到服务器保存* 2.3 刷新图书列表*/
// 2.1 创建弹框对象
const addModalDom = document.querySelector('.add-modal')
const addModal = new bootstrap.Modal(addModalDom)//利用js代码来隐藏和显示
// 保存按钮->点击->隐藏弹框
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,//它用于将 bookObj 中的所有可迭代属性展开到新的对象中。这意味着新对象将包含 bookObj 中的所有键值对。creator}}).then(result => {// console.log(result)// 2.3 添加成功后,重新请求并渲染图书列表getBooksList()// 重置表单addForm.reset()// 隐藏弹框addModal.hide()})
})
删除图书
/*** 目标3:删除图书* 3.1 删除元素绑定点击事件->获取图书id* 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.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.idaxios({url: `http://hmajax.itheima.net/api/books/${theId}`}).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]})})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})// 保存正在编辑的图书id,隐藏起来:无需让用户修改// <input type="hidden" class="id" name="id" value="84783">axios({url: `http://hmajax.itheima.net/api/books/${id}`,method: 'PUT',//修改data: {bookname,author,publisher,creator}}).then(() => {// 修改成功以后,重新获取并刷新列表getBooksList()// 隐藏弹框editModal.hide()})
})
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>
图片上传
- 获取图片文件对象
- 使用FormData携带图片文件
- 提交表单数据到服务器,使用图片url地址
<!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>
</head><body><!-- 文件选择元素 --><input type="file" class="upload"><img src="" alt="" class="my-img"><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>/*** 目标:图片上传,显示到网页上* 1. 获取图片文件* 2. 使用 FormData 携带图片文件* 3. 提交到服务器,获取图片url网址使用*/// 文件选择元素->change改变事件document.querySelector('.upload').addEventListener('change', e => {// 1. 获取图片文件console.log(e.target.files[0])// 2. 使用 FormData 携带图片文件const fd = new FormData()fd.append('img', e.target.files[0])// 3. 提交到服务器,获取图片url网址使用axios({url: 'http://hmajax.itheima.net/api/uploadimg',method: 'POST',data: fd}).then(result => {console.log(result)// 取出图片url网址,用img标签加载显示const imgUrl = result.data.data.urldocument.querySelector('.my-img').src = imgUrl})})</script>
</body></html>
input file类型的change事件
input
元素的file
类型允许用户从他们的设备上选择一个或多个文件。当用户选择了文件(或者修改了已选择的文件)后,change
事件就会被触发。这意味着如果用户通过点击文件输入框并选择了文件,或者拖拽文件到文件输入区域,change
事件监听器就会执行。FormData
FormData
是一个 JavaScript 内建对象,它主要用于构造一组键值对的数据集合,用以发送 HTTP 请求。这个对象特别适用于发送表单数据,无论是作为 AJAX 请求还是使用 Fetch API 发送数据到服务器,尤其是当涉及到文件上传时。以下是关于FormData
的一些关键特点和使用方法:特点:
- 自动构建请求体:
FormData
会根据给定的数据自动构建合适的请求体(Content-Type),这使得它在处理表单数据时非常方便,尤其是当涉及文件上传时,它会正确地设置multipart/form-data
编码。- 兼容性:支持现代浏览器,包括 IE10+,对于旧版浏览器,可能需要polyfill。
- 无需序列化:与传统的
XMLHttpRequest
发送表单数据时需要手动序列化不同,FormData
自动处理这一过程。- 文件上传:非常适合用于文件上传,因为它能够处理二进制数据。
基本用法:
创建实例:
let formData = new FormData();
添加数据:
// 添加文本字段 formData.append('key', 'value');// 添加文件 let file = document.querySelector('input[type=file]').files[0]; formData.append('file', file);// 添加多个值到同一个键 formData.append('multiValueKey', 'value1'); formData.append('multiValueKey', 'value2');
发送请求:
使用
XMLHttpRequest
或fetch
发送数据:// 使用 XMLHttpRequest let xhr = new XMLHttpRequest(); xhr.open('POST', '/api/upload', true); xhr.send(formData);// 使用 fetch fetch('/api/upload', {method: 'POST',body: formData }) then(response => response.json()) then(data => console.log(data)) catch(error => console.error('Error:', error));
注意事项:
- 当从表单直接创建
FormData
实例时,表单中的所有字段(包括文件输入)会被自动添加到FormData
中。- 可以通过
formData.get(key)
、formData.getAll(key)
、formData.has(key)
、formData.set(key, value)
、formData.delete(key)
等方法来操作数据。- 如果需要获取
FormData
中的所有键值对,可以使用formData.entries()
方法配合迭代器遍历。
FormData
是处理表单数据和文件上传的强大工具,极大地简化了从前复杂的 AJAX 请求处理过程。
更换网页背景图片
1.选择图片上传,设置body背景
2.上传成功时,保存url网址
3.网页运行后,获取url网址使用
/*** 目标:网站-更换背景* 1. 选择图片上传,设置body背景* 2. 上传成功时,"保存"图片url网址* 3. 网页运行后,"获取"url网址使用* */
//选择对应的input框绑定change事件
document.querySelector('.bg-ipt').addEventListener('change', e => {// 1. 选择图片上传,设置body背景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 imgUrl = result.data.data.urldocument.body.style.backgroundImage = `url(${imgUrl})`// 2. 上传成功时,"保存"图片url网址localStorage.setItem('bgImg', imgUrl)})
})// 3. 网页运行后,"获取"url网址使用
const bgUrl = localStorage.getItem('bgImg')
console.log(bgUrl)
// 本地有背景图才设置
bgUrl && (document.body.style.backgroundImage = `url(${bgUrl})`)
个人信息设置
步骤:
1.信息渲染
2.头像修改
3.提交表单
4.结果提示
信息渲染
自己的用户信息:给自己起个外号,并告诉服务器,获取对应的用户信息
/*** 目标1:信息渲染* 1.1 获取用户的数据* 1.2 回显数据到标签上* */
const creator = '播仔'
// 1.1 获取用户的数据
axios({url: 'http://hmajax.itheima.net/api/settings',params: {creator}
}).then(result => {const userObj = result.data.data// 1.2 回显数据到标签上Object.keys(userObj).forEach(key => {if (key === 'avatar') {// 赋予默认头像document.querySelector('.prew').src = userObj[key]} else if (key === 'gender') {//gender和头像不可通过value来改变,只有表单元素才可通过foreach来改变// 赋予默认性别// 获取性别单选框:[男radio元素,女radio元素]const gRadioList = document.querySelectorAll('.gender')// 获取性别数字:0男,1女const gNum = userObj[key]// 通过性别数字,作为下标,找到对应性别单选框,设置选中状态gRadioList[gNum].checked = true} else {// 赋予默认内容document.querySelector(`.${key}`).value = userObj[key]}})
})
头像修改
/*** 目标2:修改头像* 2.1 获取头像文件* 2.2 提交服务器并更新头像* */
// 文件选择元素->change事件
document.querySelector('.upload').addEventListener('change', e => {// 2.1 获取头像文件console.log(e.target.files[0])const fd = new FormData()fd.append('avatar', e.target.files[0])fd.append('creator', creator)// 2.2 提交服务器并更新头像axios({url: 'http://hmajax.itheima.net/api/avatar',method: 'PUT',data: fd}).then(result => {const imgUrl = result.data.data.avatar// 把新的头像回显到页面上document.querySelector('.prew').src = imgUrl})
})
提交表单(信息修改)
结果提示
给div盒子添加类名toast,会出现提示框
/*** 目标4:结果提示* 4.1 创建toast对象* 4.2 调用show方法->显示提示框*/
// 保存修改->点击
document.querySelector('.submit').addEventListener('click', () => {// 3.1 收集表单信息const userForm = document.querySelector('.user-form')const userObj = serialize(userForm, { hash: true, empty: true })userObj.creator = creator// 性别数字字符串,转成数字类型userObj.gender = +userObj.genderconsole.log(userObj)// 3.2 提交到服务器保存axios({url: 'http://hmajax.itheima.net/api/settings',method: 'PUT',data: userObj//aixos会自动将对象转化为JSON字符串}).then(result => {// 4.1 创建toast对象const toastDom = document.querySelector('.my-toast')const toast = new bootstrap.Toast(toastDom)// 4.2 调用show方法->显示提示框toast.show()})
})
AJAX原理 - XMLHttpRequest
定义:XMLHttpRequest(XHR)对象用于与服务器进行交互,通过XMLHttpRequest可以在不刷新页面的情况下请求特定URL,获取数据,这允许网页在不影响用户操作的情况下,更新页面的局部内容,XMLHttpRequest在AJAX编程中被大量使用
关系:axios内部采用XMLHttpRequest与服务器进行交互
好处:掌握使用XHR与服务器进行数据交互,了解axios内部原理
使用XMLHttpRequest
需求:获取并展示所有省份名字
/*** 目标:使用XMLHttpRequest对象与服务器通信* 1. 创建 XMLHttpRequest 对象* 2. 配置请求方法和请求 url 地址* 3. 监听 loadend 事件,接收响应结果* 4. 发起请求*/// 1. 创建 XMLHttpRequest 对象const xhr = new XMLHttpRequest()// 2. 配置请求方法和请求 url 地址xhr.open('GET', 'http://hmajax.itheima.net/api/province')// 3. 监听 loadend 事件,接收响应结果,loadend无论成功还是失败,都会执行后面的函数xhr.addEventListener('loadend', () => {console.log(xhr.response)const data = JSON.parse(xhr.response)console.log(data.list.join('<br>'))document.querySelector('.my-p').innerHTML = data.list.join('<br>')})// 4. 发起请求xhr.send()
XHR使用步骤:
- 创建XHR对象
- 调用open方法,设置url和请求方法
- 监听loadend事件,接收结果
- 调用send方法,发起请求
XMLHttpRequest- 查询参数
定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据
语法:http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2
/*** 目标:使用XHR携带查询参数,展示某个省下属的城市列表*/const xhr = new XMLHttpRequest()xhr.open('GET', 'http://hmajax.itheima.net/api/city?pname=辽宁省')xhr.addEventListener('loadend', () => {console.log(xhr.response)const data = JSON.parse(xhr.response)console.log(data)document.querySelector('.city-p').innerHTML = data.list.join('<br>')})xhr.send()
地区查询
需求:输入省份和城市名字,查询地区列表
请求地址:http://hmajax.itheima.net/api/area?参数名=值1&参数名=值2
/*** 目标: 根据省份和城市名字, 查询对应的地区列表*/// 1. 查询按钮-点击事件document.querySelector('.sel-btn').addEventListener('click', () => {// 2. 收集省份和城市名字const pname = document.querySelector('.province').valueconst cname = document.querySelector('.city').value// 3. 组织查询参数字符串const qObj = {pname,cname}// 查询参数对象 -> 查询参数字符串const paramsObj = new URLSearchParams(qObj)const queryString = paramsObj.toString()console.log(queryString)// 4. 使用XHR对象,查询地区列表const xhr = new XMLHttpRequest()xhr.open('GET', `http://hmajax.itheima.net/api/area?${queryString}`)xhr.addEventListener('loadend', () => {console.log(xhr.response)const data = JSON.parse(xhr.response)console.log(data)const htmlStr = data.list.map(areaName => {return `<li class="list-group-item">${areaName}</li>`}).join('')console.log(htmlStr)document.querySelector('.list-group').innerHTML = htmlStr})xhr.send()})
XMLHttpRequest - 数据提交
需求:通过XHR提交用户名和密码,完成注册功能
核心:
- 请求头设置Content - Type:application/json
- 请求体携带JSON字符串
<button class="reg-btn">注册用户</button><script>/*** 目标:使用xhr进行数据提交-完成注册功能*/document.querySelector('.reg-btn').addEventListener('click', () => {const xhr = new XMLHttpRequest()xhr.open('POST', 'http://hmajax.itheima.net/api/register')xhr.addEventListener('loadend', () => {console.log(xhr.response)})// 设置请求头-告诉服务器内容类型(JSON字符串)xhr.setRequestHeader('Content-Type', 'application/json')// 准备提交的数据const userObj = {username: 'itheima007',password: '7654321'}const userStr = JSON.stringify(userObj)// 设置请求体,发起请求xhr.send(userStr)})</script>