自己做的网站网页打开速度慢,学校网站建设渠道,网站导航设计模板源码,酒店管理公司网站建设方案文章目录 Day1 Ajax入门1.AJAX概念和axios的使用2. 认识URL3.URL的查询参数4.常用的请求方法和数据提交5.HTTP协议-报文6.接口文档7.form-serialize插件8.案例用户登录 Day2 Ajax综合案bootstrap弹框图书管理图片上传更换背景个人信息设置 Day3 AJAX原理XMLHttpRequestPromise封… 文章目录 Day1 Ajax入门1.AJAX概念和axios的使用2. 认识URL3.URL的查询参数4.常用的请求方法和数据提交5.HTTP协议-报文6.接口文档7.form-serialize插件8.案例用户登录 Day2 Ajax综合案bootstrap弹框图书管理图片上传更换背景个人信息设置 Day3 AJAX原理XMLHttpRequestPromise封装简易版axios案例-天气预报 Day4 AJAX进阶同步代码和异步代码回调函数地狱和Promise链式调用async和await使用事件循环EventLoop宏任务与微任务-执行任务Promise.all静态方法商品分类学习反馈 总结 资料 素材与资料都来自黑马程序员 思维导图 mdn网址 Day1 Ajax入门
1.AJAX概念和axios的使用 概念AJAX是浏览器与服务器进行数据通信的技术 作用浏览器和服务器之间通信动态数据交互。 怎么使用AJAX 1.先使用axios库与服务器进行数据通信使用场景VUEreat项目都会用到axios 2.再学习XMLHttpREquest对象的使用理解AJAX底层原理 axios使用
1.引入axios库 script srchttps://cdn.jsdelivr.net/npm/axios/dist/axios.min.js/script2.使用axios函数 √ 传入配置对象 √ 再用.then回调函数接收结果并做后续的处理
axios({url:目标资源地址
}).then(result {
//对服务器进行后续的处理
})2. 认识URL
URL:统一资源定位符网址用于访问服务器资源 解释url每个部分的作用 http://hmajax.itheima.net /api/login 协议域名 资源路径 3.URL的查询参数
定义浏览器提供给服务器额外信息让服务器返回浏览器想要的数据 语法http://xxxx.com/xxx/xxx?参数名1值1参数名2值2 URL的查询参数的作用浏览器提供给服务器额外信息获取对应的数据 axios-查询参数 使用params选项携带参数名和值 axios在运行时把参数名和值会拼接到url?参数名值
axios({url:目标资源地址,params:{参数名值
}).then(result {
//对服务器进行后续的处理
})4.常用的请求方法和数据提交
请求方法对服务器资源要执行的操作
请求方法操作GET获取数据POST数据提交PUT修改数据全部DELETE删除数据PATCH修改数据部分
数据提交当数据需要在服务器上保存 axios请求配置
url:请求的URL网址method:请求的方法GET可以省略不区分大小写data:提交数据
axios({url:目标资源地址,params:{参数名值},data:{参数名值}
}).then(result {
//对服务器进行后续的处理
})axios-错误处理
axios({//请求选项
}).then(result {//处理数据
}).catch(error {//处理错误
})5.HTTP协议-报文
请求报文浏览器发送给服务器的内容叫做请求报文请求报文的组成 1.请求行请求方法URL协议 2.请求头以键值对的格式携带的附加信息比如Content-Type 3.空行分隔请求头空行之后的是发送给服务器的资源感觉我的浏览器有点不一样 4.请求体发送的资源 通过Chrome的网络面板查看请求报文 响应报文的组成
1.响应行协议、Http响应状态码、状态信息2.响应头键值对的格式携带的附加信息比如Content-Type3.空行分隔响应头空行之后的是返回给浏览器的资源4.响应体返回的资源
Http响应状态码用来表明请求是否成功完成。
状态码说明1xx信息2xx成功3xx重定向消息4xx客户端错误5xx服务端错误
6.接口文档
接口文档由后端提供的描述接口的文章
7.form-serialize插件
作用快速收集表单元素的值。 素材
!DOCTYPE html
html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title13.form-serialize插件使用/title
/headbodyform actionjavascript:; classexample-forminput typetext nameunamebrinput typetext namepwdbrinput typebutton classbtn value提交/form!-- 目标在点击提交时使用form-serialize插件快速收集表单元素值--scriptdocument.querySelector(.btn).addEventListener(click, () {})/script
/body/htmlscript src./lib/form-serialize.js/scriptscriptdocument.querySelector(.btn).addEventListener(click, () {/* 2.使用serialize函数快速收集表单元素的值参数1要获得哪个表单的数据表单元素设置name属性值会作为对象的属性名建议name属性的值最好和接口文档参数名一致参数2配置对象hash:设置获取数据结构-true:JS对象推荐 一般请求体里提交给服务器-false查询字符串empty:设置是否获取空值-true获取空值推荐数据结构和标签结构一致-false:不获得空值*/const form document.querySelector(.example-form)// const data serialize(form,{hash:true,empty:true})// const data serialize(form,{hash:false,empty:true})const data serialize(form,{hash:true,empty:false})console.log(data);})/script8.案例用户登录
素材
!DOCTYPE html
html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0title12.案例_登录_提示消息/title!-- 引入bootstrap.css --link relstylesheet hrefhttps://cdn.jsdelivr.net/npm/bootstrap5.2.2/dist/css/bootstrap.min.css!-- 公共 --stylehtml,body {background-color: #EDF0F5;width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;}.container {width: 520px;height: 540px;background-color: #fff;padding: 60px;box-sizing: border-box;}.container h3 {font-weight: 900;}/style!-- 表单容器和内容 --style.form_wrap {color: #8B929D !important;}.form-text {color: #8B929D !important;}/style!-- 提示框样式 --style.alert {transition: .5s;opacity: 0;}.alert.show {opacity: 1;}/style
/headbodydiv classcontainerh3欢迎-登录/h3!-- 登录结果-提示框 --div classalert alert-success rolealert提示消息/div!-- 表单 --div classform_wrapformdiv classmb-3label forusername classform-label账号名/labelinput typetext classform-control username/divdiv classmb-3label forpassword classform-label密码/labelinput typepassword classform-control password/divbutton typebutton classbtn btn-primary btn-login 登 录 /button/form/div/divscript srchttps://cdn.jsdelivr.net/npm/axios/dist/axios.min.js/scriptscript// 目标1点击登录时用户名和密码长度判断并提交数据和服务器通信// 目标2使用提示框反馈提示消息// 1.1 登录-点击事件document.querySelector(.btn-login).addEventListener(click, () {// 1.2 获取用户名和密码const username document.querySelector(.username).valueconst password document.querySelector(.password).value// console.log(username, password)// 1.3 判断长度if (username.length 8) {console.log(用户名必须大于等于8位)return // 阻止代码继续执行}if (password.length 6) {console.log(密码必须大于等于6位)return // 阻止代码继续执行}// 1.4 基于axios提交用户名和密码// console.log(提交数据到服务器)axios({url: http://hmajax.itheima.net/api/login,method: POST,data: {username,password}}).then(result {console.log(result)console.log(result.data.message)}).catch(error {console.log(error)console.log(error.response.data.message)})})/script
/body/htmlscript// 目标1点击登录时用户名和密码长度判断并提交数据和服务器通信// 目标2使用提示框反馈提示消息// 1.1 登录-点击事件document.querySelector(.btn-login).addEventListener(click, () {// 1.2 获取用户名和密码const username document.querySelector(.username).valueconst password document.querySelector(.password).value// console.log(username, password)// 1.3 判断长度if (username.length 8) {console.log(用户名必须大于等于8位)return // 阻止代码继续执行}if (password.length 6) {console.log(密码必须大于等于6位)return // 阻止代码继续执行}// 1.4 基于axios提交用户名和密码// console.log(提交数据到服务器)axios({url: http://hmajax.itheima.net/api/login,method: POST,data: {username,password}}).then(result {console.log(result)console.log(result.data.message)}).catch(error {console.log(error)console.log(error.response.data.message)})})/scriptDay2 Ajax综合案
bootstrap弹框
bootstrap中文文档
属性控制方式
!DOCTYPE htmlhtml langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleBootstrap 弹框/title!-- 引入bootstrap.css --link hrefhttps://cdn.jsdelivr.net/npm/bootstrap5.2.2/dist/css/bootstrap.min.css relstylesheet
/headbody!-- 目标使用Bootstrap弹框1. 引入bootstrap.css 和 bootstrap.js2. 准备弹框标签确认结构3. 通过自定义属性控制弹框的显示和隐藏--button typebutton classbtn btn-primary data-bs-target .my-box data-bs-togglemodal显示弹框/button!-- 弹框标签 bootstrap的标签modal弹框添加modal类名默认隐藏--div classmodal my-box tabindex-1div classmodal-dialog!-- 弹框内容 --div classmodal-contentdiv classmodal-headerh5 classmodal-titleModal title/h5button typebutton classbtn-close data-bs-dismissmodal aria-labelClose/button/divdiv classmodal-bodypModal body text goes here./p/divdiv classmodal-footerbutton typebutton classbtn btn-secondary data-bs-dismissmodalClose/buttonbutton typebutton classbtn btn-primarySave changes/button/div/div/div/div!-- 引入bootstrap.js --script srchttps://cdn.jsdelivr.net/npm/bootstrap5.2.2/dist/js/bootstrap.min.js/script
/body/htmljs属性控制
!DOCTYPE html
html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleBootstrap 弹框/title!-- 引入bootstrap.css --link hrefhttps://cdn.jsdelivr.net/npm/bootstrap5.2.2/dist/css/bootstrap.min.css relstylesheet
/headbody!-- 目标使用JS控制弹框显示和隐藏1. 创建弹框对象2. 调用弹框对象内置方法.show() 显示.hide() 隐藏--button typebutton classbtn btn-primary edit-btn编辑姓名/buttondiv classmodal name-box tabindex-1div classmodal-dialogdiv classmodal-contentdiv classmodal-headerh5 classmodal-title请输入姓名/h5button typebutton classbtn-close data-bs-dismissmodal aria-labelClose/button/divdiv classmodal-bodyform actionspan姓名/spaninput typetext classusername/form/divdiv classmodal-footerbutton typebutton classbtn btn-secondary data-bs-dismissmodal取消/buttonbutton typebutton classbtn btn-primary save-btn保存/button/div/div/div/div!-- 引入bootstrap.js --script srchttps://cdn.jsdelivr.net/npm/bootstrap5.2.2/dist/js/bootstrap.min.js/scriptscript// q.创建弹框对象const modalDom document.querySelector(.name-box)const modal new bootstrap.Modal(modalDom)// 编辑姓名--点击--赋予默认姓名 --弹框显示document.querySelector(.edit-btn).addEventListener(click,(){document.querySelector(.username).value 默认姓名// 显示弹框modal.show()})
// 保存--点击---弹框隐藏document.querySelector(.save-btn).addEventListener(click,(){const username document.querySelector(.username).value console.log(模拟将姓名保存在服务器当中,username);// 隐藏弹框modal.hide()})/script/body/html图书管理
步骤如下
目标1渲染图书列表 1.1 获取数据 1.2 渲染数据 const creator 老张
// 封装-获取被渲染图书列表函数
function getBookList(){// 1.1获取数据axios({url:http://hmajax.itheima.net/api/books,params:{// 外号获取对应数据creator}}).then(result {// console.log(result);// console.log(result.data.data);const bookList result.data.data// 1.2渲染数据const htmlStr bookList.map((item,index) {return trtd${index1}/tdtd${item.bookname}/tdtd${item.author}/tdtd${item.publisher}/tdtd data-id${item.id}span classdel删除/spanspan classedit编辑/span/td/tr }).join()// console.log(htmlStr);document.querySelector(.list).innerHTML htmlStr})
}
getBookList()
目标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添加成功之后重新请求并渲染图书列表getBookList()// 重置表单addForm.reset()// 隐藏弹框addModal.hide()})
})目标3 删除图书 3.1 删除元素绑定点击事件 - 获取图书id 3.2 调用删除接口 3.3刷新图书列表 // 3.1 删除元素绑定点击事件 - 获取图书id
// 事件委托
document.querySelector(.list).addEventListener(click,e {// 获取触发事件目标元素// 判断点击的是删除元素if(e.target.classList.contains(del)){// console.log(删除元素);// 获取图书id(自定义属性)const theId e.target.parentNode.dataset.idconsole.log(theId);// 3.2 调用删除接口axios({url:http://hmajax.itheima.net/api/books/${theId},method:delete}).then(() {// 3.3刷新图书列表getBookList()})}
})
目标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// 数据对象“属性”和标签“类名”一致// 遍历数据对象使用属性去获得对应的标签快速赋值const keys Object.keys(bookObj)console.log(keys);// [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 typehidden classid nameid value230530axios({url:http://hmajax.itheima.net/api/books/${id},method:put,data:{bookname,author,publisher,creator}}).then(() {// 修改成功以后重新1获取并刷新列表getBookList()})editModal.hide()
})图片上传 1. 获取图片文件2. 使用 FormData 携带图片文件3. 提交到服务器获取图片url网址使用script srchttps://cdn.jsdelivr.net/npm/axios/dist/axios.min.js/scriptscript// 文件选择元素-change事件document.querySelector(.upload).addEventListener(change,e {// 1. 获取图片文件// console.dir(e.target)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更换背景 目标网站-更换背景1. 选择图片上传设置body背景2. 上传成功时保存图片url网址3. 网页运行后获取url网址使用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])// 提交到服务器获取图片url网址使用axios({url:http://hmajax.itheima.net/api/uploadimg,method:post,data:fd}).then(result {// console.dir(result); const imgUrl result.data.data.urldocument.body.style.backgroundImage url(${imgUrl})// 2. 上传成功时保存图片url网址localStorage.setItem(bgImg,imgUrl)})
})// 网页运行后获取url网址使用
const bgUrl localStorage.getItem(bgImg)
console.log(bgUrl);
bgUrl (document.body.style.backgroundImage url(${bgUrl}))
个人信息设置 目标1信息渲染1.1 获取用户的数据1.2 回显数据到标签上const creator 张三
axios({url:http://hmajax.itheima.net/api/settings,params:{creator}
}).then(result {const userObj result.data.dataconsole.log(userObj);// 1.2回显数据到标签上Object.keys(userObj).forEach(key {if(key avatar){// 赋予默认头像document.querySelector(.prew).src userObj[key]}else if(key gender){// 赋予默认性别// 获取性别单选框[男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 {console.log(result);// data.data.avatarconst imgUrl result.data.data.avatardocument.querySelector(.prew).src imgUrl})})
/*
目标3提交表单3.1 收集表单元素3.2 提交到服务器
目标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}).then( result {// 4.1 创建toast对象const toastDom document.querySelector(.my-toast)const toast new bootstrap.Toast(toastDom)// 4.2 调用show方法- 显示提示框toast.show()})
})Day3 AJAX原理
XMLHttpRequest
XMLHttpRequestXHR对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL获取数据。这允许网页在不影响用户操作的情况下更新页面的局部内容。XMLHttpRequest 在 AJAX 编程中被大量使用。 AJAX原理XMLHttpRequest对象; 学习XHR原因 1.有更多与服务器数据通信方式 2.了解axios内部原理 XHR使用步骤
创建XHR对象调用open方法设置url和请求方法监听loadend事件接收结果调用send方法发起请求
let xhr new XMLHttpRequest()
xhr.open(请求方法,请求url网址)
xhr.addEventlistener(loadend,(){//响应结果console.log(xhr.response) 接收响应
})
xhr.send() 发送请求Promise
概念表示管理一个异步操作最终状态和结果值的对象
好处 1.逻辑清晰 2.了解axios函数内部运作机制 3.能解决回调函数地狱问题 学习promise对象原因 √ 成功和失败状态可以管理对于处理程序 √ 了解axios内部原理 promise使用步骤 script/*** 目标使用Promise管理异步任务*/// 1.创建promise对象pending待定状态const p new Promise((resolve, reject) {// Promise对象创建这里的代码都会执行// 2.执行代码setTimeout(() {// resolve()fulfilled状态--已兑现 then() resolve(模拟AJAX请求-成功结果)// reject()reject状态--已拒绝 catch()reject(new Error(模拟AJAX请求-失败结果))}, 2000)})console.log(p);// 3.获取结果p.then(result {console.log(result);}).catch(error {console.log(error);})/script目标使用Promise管理XHR请求省份列表1. 创建Promise对象2. 执行XHR异步代码获取省份列表3. 关联成功或失败函数做后续处理script// 1. 创建Promise对象const p new Promise((resolve,reject) {// 2. 执行XHR异步代码获取省份列表const xhr new XMLHttpRequest()xhr.open(GET,http://hmajax.itheima.net/api/province)xhr.addEventListener(loadend,(){// xhr如何判断响应成功还是失败的// 2xx开头的都是成功响应状态码console.log(xhr);if(xhr.status 200 xhr.status 300){resolve(JSON.parse(xhr.response))}else{reject(new Error(xhr.response))}})xhr.send()})//3. 关联成功或失败函数做后续处理p.then((result){console.log(result);document.querySelector(.my-p).innerHTML result.list.join(br)}).catch(error{// 错误对象要用console.dir详细打印console.dir(error);// 服务器返回错误提示消息插入p标签document.querySelector(.my-p).innerHTML error.message}) /script封装简易版axios 目标封装_简易axios函数_获取省份列表1. 定义myAxios函数接收配置对象返回Promise对象2. 发起XHR请求默认请求方法为GET3. 调用成功/失败的处理程序4. 使用myAxios函数获取省份列表展示script// 1. 定义myAxios函数接收配置对象返回Promise对象function myAxios(config){return new Promise((resolve,reject) {// 2. 发起XHR请求默认请求方法为GETconst xhr new XMLHttpRequest()xhr.open(GET||config.method,config.url)// 3. 调用成功/失败的处理程序xhr.addEventListener(loadend,(){if(xhr.status 200 xhr.status 300){resolve(JSON.parse(xhr.response))}else{reject(new Error(xhr.response))}})xhr.send()})}myAxios({url:http://hmajax.itheima.net/api/province}).then(result {console.log(result);document.querySelector(.my-p).innerHTML result.list.join(br)}).catch(error {console.dir(error);document.querySelector(.my-p).innerHTML error.message})/script目标封装_简易axios函数_获取地区列表1. 判断有params选项携带查询参数2. 使用URLSearchParams转换并携带到url上3. 使用myAxios函数获取地区列表scriptfunction myAxios(config) {if(config.params){const paramsObj new URLSearchParams(config.params)const queryString paramsObj.toString()config.url config.url?${queryString}}return new Promise((resolve, reject) {const xhr new XMLHttpRequest()xhr.open(config.method || GET, config.url)xhr.addEventListener(loadend, () {if (xhr.status 200 xhr.status 300) {resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})xhr.send()})}myAxios({url:http://hmajax.itheima.net/api/area,params:{pname:广东省,cname:河源市}}).then((result){console.log(result);document.querySelector(.my-p).innerHTML result.list.join(br)}).catch(error{// 错误对象要用console.dir详细打印console.dir(error);// 服务器返回错误提示消息插入p标签document.querySelector(.my-p).innerHTML error.message}) /script目标封装_简易axios函数_注册用户1. 判断有data选项携带请求体2. 转换数据类型在send中发送3. 使用myAxios函数完成注册用户scriptfunction myAxios(config) {return new Promise((resolve, reject) {const xhr new XMLHttpRequest()if (config.params) {const paramsObj new URLSearchParams(config.params)const queryString paramsObj.toString()config.url ?${queryString}}xhr.open(config.method || GET, config.url)xhr.addEventListener(loadend, () {if (xhr.status 200 xhr.status 300) {resolve(JSON.parse(xhr.response))} else {reject(new Error(xhr.response))}})if(config.data){// 告诉服务器我传递的内容类型是JSON字符串xhr.setRequestHeader(Content-Type,application/json)// 准备数据并转成JSON字符串xhr.send(JSON.stringify(config.data))}else{xhr.send()} })}document.querySelector(.reg-btn).addEventListener(click,() {myAxios({url:http://hmajax.itheima.net/api/register,method:POST,data:{username:zz111111111222,password:12345111226}}).then((result){console.log(result);// document.querySelector(.my-p).innerHTML result.list.join(br)}).catch(error{// 错误对象要用console.dir详细打印console.dir(error);// 服务器返回错误提示消息插入p标签// document.querySelector(.my-p).innerHTML error.message}) })/script案例-天气预报 目标1默认显示-北京市天气1.1 获取北京市天气数据1.2 数据展示到页面// 获取并渲染城市天气函数 function getWeather(cityCode){
// 1.1获取北京市天气数据myAxios({url:http://hmajax.itheima.net/api/weather,params:{city:cityCode }}).then(result {console.log(result);const wObj result.data// 1.2数据展示到页面const dateStr span classdateShort${wObj.date}/spanspan classcalendar农历nbsp;span classdateLunar${wObj.dateLunar}/spandocument.querySelector(.title).innerHTMLdateStr// 城市名字document.querySelector(.area).innerHTML wObj.area// 当天天气const nowWStr div classtem-boxspan classtempspan classtemperature${wObj.temperature}/spanspan°/span/span/divdiv classclimate-boxdiv classairspan classpsPm25${wObj.psPm25}/spanspan classpsPm25Level${wObj.psPm25Level}/span/divul classweather-listliimg src${wObj.weatherImg} classweatherImg altspan classweather${wObj.weather}/span/lili classwindDirection${wObj.windDirection}/lili classwindPower${wObj.windPower}/li/ul/divdocument.querySelector(.weather-box).innerHTML nowWStr
// 当前天气const twObj wObj.todayWeatherconsole.log(twObj);const todayWStr div classrange-boxspan今天/spanspan classrangespan classweather${twObj.weather}/spanspan classtemNight${twObj.temNight}/spanspan-/spanspan classtemDay${twObj.temDay}/spanspan℃/span/span
/div
ul classsun-listlispan紫外线/spanspan classultraviolet${twObj.ultraviolet}/span/lilispan湿度/spanspan classhumidity${twObj.humidity}/span%/lilispan日出/spanspan classsunriseTime${twObj.sunriseTime}/span/lilispan日落/spanspan classsunsetTime${twObj.sunsetTime}/span/li
/ul
document.querySelector(.today-weather).innerHTML todayWStr
// 7天天气预报
const dayForecast wObj.dayForecast
const dayForecastStr dayForecast.map(item {return li classitemdiv classdate-boxspan classdateFormat${item.dateFormat}/spanspan classdate${item.date}/span/divimg src${item.weatherImg} alt classweatherImgspan classweather${item.weather}/spandiv classtempspan classtemNight${item.temNight}/span-span classtemDay${item.temDay}/spanspan℃/span/divdiv classwindspan classwindDirection${item.windDirection}/spanspan classwindPowerlt;${item.windPower}/span/div/li
}).join()
document.querySelector(.week-wrap).innerHTMLdayForecastStr}).catch(error {console.log(error);})
}
//默认进入网页-就要获取天气数据
getWeather(110100)
目标2搜索城市列表2.1绑定input手机开你获取关键字2.2获取城市列表数据// 2.1绑定input手机开你获取关键字
document.querySelector(.search-city).addEventListener(input,e {// 2.2获取城市列表数据console.log(e.target.value);myAxios({url:http://hmajax.itheima.net/api/weather/city,params:{city: e.target.value}}).then(result {console.log(result);const liStr result.data.map(item {return li classcity-item data-code${item.code}${item.name}/li}).join()console.log(liStr);const a document.querySelector(.search-list).innerHTML liStrconsole.log(a);}).catch(error {console.dir(error)})
})目标3切换城市天气3.1绑定城市点击事件获取城市code值3.2 调用获取并展示天气的函数document.querySelector(.search-list).addEventListener(click,e {if(e.target.tagName LI){getWeather(e.target.dataset.code)}
})Day4 AJAX进阶
同步代码和异步代码
同步代码逐行执行需原地等待结果后才继续向下执行 异步代码调用后耗时不阻塞代码继续执行不必原地等待在将来完成后触发一个回调函数。 Js中的异步代码setTimeout/setInterval,事件AJAX
回调函数地狱和Promise链式调用
1.回调函数地狱 在回调函数一直向下嵌套回调函数形成回调函数地狱 目标演示回调函数地狱 需求获取默认第一个省第一个市第一个地区并展示在下拉菜单中 概念在回调函数中嵌套回调函数一直嵌套下去就形成了回调函数地狱 缺点可读性差异常无法获取耦合性严重牵一发动全身 scriptaxios({url:http://hmajax.itheima.net/api/province}).then(result {const pname result.data.list[0]document.querySelector(.province).innerHTML pname// 2.获取默认第一个城市的名字axios({url:http://hmajax.itheima.net/api/city, params:{pname}}).then(result {const cname result.data.list[0]document.querySelector(.city).innerHTML cname// 3.获取默认第一个地区的名字axios({url:http://hmajax.itheima.net/api/area,params:{pname,cname}}).then(result {const areaName result.data.list[0]document.querySelector(.area).innerHTML areaName})})})/script2.Promise的链式调用–入门 概念依靠then()方法会返回一个新生成的Promise对象特性继续初恋下一环任务直到结束 细节then()回调函数中的返回值会影响新生成的Promise对象最终状态和结果 目标掌握Promise的链式调用 需求把省市的嵌套结构改成链式调用的线性结构 script// 1.创建Promise对象-模拟请求省份名字const p new Promise((resolve, reject) {setTimeout(() {resolve(北京市)}, 2000)})// 2.获取省份的名字const p2 p.then(result {return new Promise((resolve, reject) {setTimeout(() {resolve(result -----北京市)}, 2000)})})// 4.获取城市名字p2.then(result {console.log(result);})/script3.解决回调函数地狱
目标把回调函数嵌套代码改成Promise链式调用结构
需求获取默认第一个省第一个市第一个地区并展示在下拉菜单中scriptlet pname axios({url:http://hmajax.itheima.net/api/province}).then(result {pname result.data.list[0]document.querySelector(.province).innerHTML pname// 2.获取默认第一个城市的名字return axios({url:http://hmajax.itheima.net/api/city, params:{pname}}).then(result {const cname result.data.list[0]document.querySelector(.city).innerHTML cname// 3.获取默认第一个地区的名字return axios({url:http://hmajax.itheima.net/api/area,params:{pname,cname}}).then(result {const areaName result.data.list[0]document.querySelector(.area).innerHTML areaName})})})async和await使用
概念;在async函数内使用await关键字取代then函数等待获取Promise对象成功状态的结果值 async函数和await捕获错误使用 try…catch…
script srchttps://cdn.jsdelivr.net/npm/axios/dist/axios.min.js/scriptscript/*** 目标掌握async和await语法解决回调函数地狱* 概念在async函数内使用await关键字获取Promise对象成功状态结果值* 注意await必须用在async修饰的函数内await会阻止异步函数内代码继续执行原地等待结果*/// 1.定义async修饰函数async function getData(){try {/*要执行的代码*/const pObj await axios({url:http://hmajax.itheima.net/api/province})const pname pObj.data.list[0]const cObj await axios({url:http://hmajax.itheima.net/api/city,params:{pname}})const cname cObj.data.list[0]const aObj await axios({url:http://hmajax.itheima.net/api/area1,params:{pname,cname}})const areaName aObj.data.list[0]document.querySelector(.province).innerHTML pnamedocument.querySelector(.city).innerHTML cnamedocument.querySelector(.area).innerHTML areaName} catch (error) {/* error接收的是错误信息try里代码如果有错误直接进入这里执行*/console.dir(error);}}getData()/script事件循环EventLoop
概念JavaScript 有一个基于事件循环的并发模型事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。这个模型与其他语言中的模型截然不同比如 C 和 Java。 原因;JavaScript单线程某一时刻只能执行一行代码为了让耗时代码不阻塞其他代码运行设计了事件循环模型。 JavaScript内代码如何执行 1.执行同步代码遇到异步代码交给宿主浏览器环境执行 2.异步有了结果后把回调函数放入任务队列排队 3.当调用栈空闲后反复调用任务队列里的回调函数 script/*** 目标阅读并回答执行的顺序结果*/console.log(1)setTimeout(() {console.log(2)}, 0)console.log(3)setTimeout(() {console.log(4)}, 2000)console.log(5)/script事件循环练习 script/*** 目标阅读并回答执行的顺序结果* 1 5 3 2 4 6点击时触发*/console.log(1)setTimeout(() {console.log(2)}, 0)function myFn() {console.log(3)}function ajaxFn() {const xhr new XMLHttpRequest()xhr.open(GET, http://hmajax.itheima.net/api/province)xhr.addEventListener(loadend, () {console.log(4)})xhr.send()}for (let i 0; i 1; i) {console.log(5)}ajaxFn()document.addEventListener(click, () {console.log(6)})myFn()/script事件·循环·练习 宏任务与微任务-执行任务
宏任务 浏览器执行的异步代码例如JS执行脚本事件setTimeout/setInterval,AJAX请求完成事件用户交互事件等。
微任务:JS引擎执行的异步代码例如Promise对象.then()的回调 JavaScript内代码如何执行 1.执行第一个script脚本时间宏任务里面同步代码 2.遇到宏任务/微任务交给宿主环境有结果回调函数进入对应队列 当执行栈空闲时清空微任务队列再执行下一个宏任务从1再来 script// 目标回答代码执行顺序console.log(1)setTimeout(() {console.log(2)const p new Promise(resolve resolve(3))p.then(result console.log(result))}, 0)const p new Promise(resolve {setTimeout(() {console.log(4)}, 0)resolve(5)})p.then(result console.log(result))const p2 new Promise(resolve resolve(6))p2.then(result console.log(result))console.log(7)/script事件循环-执行过程 Promise.all静态方法
概念合并多个Promise对象等待所有提示成功完成或某一个失败做后续逻辑 script srchttps://cdn.jsdelivr.net/npm/axios/dist/axios.min.js/scriptscript/*** 目标掌握Promise的all方法作用和使用场景* 业务当我需要同一时间显示多个请求的结果时就要把多请求合并* 例如默认显示北京, 上海, 广州, 深圳的天气在首页查看* code* 北京-110100* 上海-310100* 广州-440100* 深圳-440300*/// 1.请求城市天气得到Promise对象const bjObj axios({url:http://hmajax.itheima.net/api/weather,params:{city:110100}})const shObj axios({url:http://hmajax.itheima.net/api/weather,params:{city:310100}})const gzObj axios({url:http://hmajax.itheima.net/api/weather,params:{city:440100}})const szObj axios({url:http://hmajax.itheima.net/api/weather,params:{city:440300}})// console.log(bjObj,shObj, gzObj,szObj);// 2.使用 Promise.all合并对各Promise对象const p Promise.all([bjObj,shObj, gzObj,szObj])p.then(result {console.log(result);// 注意结果数组顺序和合并时顺序是一致的const htmlStr result.map(item {// 解构赋值const {area,weather}item.data.datareturn li${area}-----${weather}/li }).join()document.querySelector(.my-ul).innerHTML htmlStr}).catch(error {console.dir(eerror)})/script商品分类 目标把所有商品分类“同时”渲染到页面上1. 获取所有一级分类数据2. 遍历id创建获取二级分类请求3. 合并所有二级分类Promise对象4. 等待同时成功后渲染页面script// 1. 获取所有一级分类数据axios({url:http://hmajax.itheima.net/api/category/top}).then(result {console.log(result);// 2. 遍历id创建获取二级分类请求const promiseList result.data.data.map(item {return axios({url:http://hmajax.itheima.net/api/category/sub,params:{id:item.id}})})console.log(promiseList);// 3. 合并所有二级分类Promise对象const p Promise.all(promiseList)p.then(result {console.log(result);// 4. 等待同时成功后渲染页面const htmlStr result.map(item {const obj item.data.datareturndiv classitemh3一级分类名字${obj.name}/h3ul${obj.children.map(item {return lia hrefjavascript:;img src${item.picture}p${item.name}/p/a/li}).join()}/ul/div}).join()document.querySelector(.sub-list).innerHTML htmlStr})})/script学习反馈 目标1完成省市区下拉列表切换1.1 设置省份下拉菜单数据1.2 切换省份设置城市下拉菜单数据清空地区下拉菜单1.3 切换城市设置地区下拉菜单数据目标2收集数据保存2.1 监听提交的点击事件2.2 依靠插件收集表单数据2.3 基于axios提交保存/*** 目标1完成省市区下拉列表切换* 1.1 设置省份下拉菜单数据* 1.2 切换省份设置城市下拉菜单数据清空地区下拉菜单* 1.3 切换城市设置地区下拉菜单数据*/
// 1.1 设置省份下拉菜单数据
axios({url:http://hmajax.itheima.net/api/province}).then(result {const optionStr result.data.list.map(item {return option value${item}${item}/option}).join()document.querySelector(.province).innerHTMLoption value省份/optionoptionStr
})// 1.2 切换省份设置城市下拉菜单数据清空地区下拉菜单
document.querySelector(.province).addEventListener(change,async e {// 获取用户选择的省份名字console.log(e.target.value);const result await axios({url:http://hmajax.itheima.net/api/city,params:{pname:e.target.value}}).then(result {const optionStr result.data.list.map(item {return option value${item}${item}/option}).join()// 把默认初始选项下属城市数据插入select中 document.querySelector(.city).innerHTMLoption value城市/optionoptionStr // 清空地区数据document.querySelector(.area).innerHTML option value地区/option})
})// 1.3 切换城市设置地区下拉菜单数据document.querySelector(.city).addEventListener(change,async e {console.log(e.target.value);const result await axios({url:http://hmajax.itheima.net/api/area,params:{pname: document.querySelector(.province).value,cname:e.target.value}}).then(result {const optionStr result.data.list.map(item {return option value${item}${item}/option}).join()document.querySelector(.area).innerHTMLoption value地区/optionoptionStr })
})
/* 目标2收集数据保存2.1 监听提交的点击事件2.2 依靠插件收集表单数据2.3 基于axios提交保存
*/
// 2.1 监听提交的点击事件
document.querySelector(.submit).addEventListener(click,async () {// 2.2 依靠插件收集表单数据const form document.querySelector(.info-form)const data serialize(form,{hash:true,empty:true})console.log(data);// 2.3 基于axios提交保存try {const result await axios({url:http://hmajax.itheima.net/api/feedback,method:post,data })console.log(result);alert(result.data.message)} catch (error) {console.dir(error);alert(error.response.data.message)}})
总结 学习了这门课程AJAX的大概知识我都清楚了也在学习过程中我得到了一些学习经验比如看完一天的视频要回去复习不然容易忘记边看视频边敲代码边理解或者看完一天视频再敲代码可能带着回忆的状态这样子可以检验自己是否真的懂可能这个方法会好一点因人而异还有就是代码也不是敲一遍就行的最多敲三遍最后一遍一定是自己明白了在不借助外力的情况下自己敲虽然但是我还没达到那种境界在努力中。 最后送大家一句话博学之审问之慎思之明辨之笃行之。