当前位置: 首页 > news >正文

Ajax笔记(下)

一、图片上传

1.什么是图片上传?
就是把本地的图片上传到网页显示

2.图片上传怎么做?
先依靠文件选择元素获取用户选择的本地文件,接着提交到服务器保存,服务器会返回图片的url网址,然后把网址加载到img标签的src属性即可显示

3.为什么不直接显示到浏览器上,要放到服务器上呢?
因为浏览器保存时临时的,如果你想随时随地访问图片,需要上传到服务器上

4.图片上传怎么做呢?
(1)先获取图片文件对象

(2)使用FormData表单数据对象装入(因为图片是文件而不是以前的数字和字符了,所以传递文件一般需要放入FormData一键只对文件流的数据传递)

(3)提交表单数据对象,使用服务器返回图片url网址

5.核心代码

<!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>

总结(图片上传的思路):

先用文件选择元素,获取到文件对象,然后装入 FormData 表单对象中,再发给服务器,得到图片在服务器的 URL 网址,再通过 img 标签加载图片显示

二、案例-网站-更换背景图

1.步骤:
(1)先获取到用户选择的背景图片,上传并把服务器返回的图片url网址设置给body背景

(2)上传成功时,保存图片url网址到localStorage中

(3)网页运行后,获取localStorage中的图片的url网址使用(并判断本地有图片url网址字符串才设置)

2.核心代码

/*** 目标:网站-更换背景*  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])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})`)

总结(localStorage取值和复制的语法分别是什么):

localStorage.getItem(‘key’)是取值,localStorage.setItem('key',value)赋值

三、案例-个人信息设置

1.分析:

(1)先完成信息回显

(2)再做头像修改-立刻就更新给此用户

(3)收集个人信息表单-提交保存

(4)提交后反馈结果给用户(提示框)

2.信息渲染

(1)获取数据

(2)渲染到页面上

3.头像修改

步骤:
(1)获取到用户选择的头像文件

(2)调用头像修改接口,并除了头像文件外,还要在FormData表单数据中携带外号

(3)提交到服务器保存此用户对应头像文件,并把返回的头像图片的url网址设置到页面上

(3)注意:重新刷新重新获取,已经是修改后的头像

(4)核心代码:

/*** 目标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})
})

总结:为什么这次上传头像,需要携带外号呢?
因为这次头像上传到后端,是要保存在某个用户名下的,所以需要把外号名字一起携带过去、

4.信息修改:

需求:点击提交按钮,收集个人信息,提交到服务器保存(无需重新获取刷新,因为页面已经是最新的数据了)

(1)收集表单数据

(2)提交到服务器保存-调用用户信息更新接口(注意请求方式是PUT)代表数据更新的意思

核心代码:

/*** 目标3:提交表单*  3.1 收集表单信息*  3.2 提交到服务器保存*/
// 保存修改->点击
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 => {})
})

总结:信息修改数据和以前的增删改查哪个实现的思路比较接近呢?
编辑:首先是回显已经做完了,然后收集用户最新改动后的数据,提交到服务器上保存,因为页面最终就是用户刚写的数据,所以不用重新获取并刷新页面了。

5.提示框

(1)需求:使用bootStrap提示框和modal弹框使用很像,语法如下:

首先准备对应的标签结构,然后设置延迟自动显示的时间

<div class="toast" data-bs-delay="1500">
提示框内容
</div>

最后:使用js的方式,在axios请求响应成功时,展示结果

// 创建提示框对象
const toastDom = document.querySelector('css选择器')
const toast = new bootstrap.Toast(toastDom)

// 显示提示框
toast.show()

核心代码:

/*** 目标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()})
})

总结:bootstrap弹框什么使用js显示呢?

需要执行一些其他的js逻辑后,再去显示/隐藏弹框时。

四、知识点自测

1.什么方法可以将js数据类型改成json数据类型?

        JSON.stringfy()

2.以下哪个方法,会延迟一段时间,再执行函数体,并执行一次就停止?

A、setTImeout(函数体,毫秒值)

B、setInterval(函数体,毫秒值)

        选择A,

3.下列代码结果是多少?

A、true
B、大于
C、240
D、false

let obj = {
status: 240
}
const result = obj.status >= 200 && obj.status < 300

        结果是Atrue

4.代码运行结果是多少?

let result = 'http://www.baidu.com'
result += '?a=10'
result += '&b=20'

A、http://www.baidu.com
B、?a=10
C、&b=20
D、http://www.baidu.com?a=10&b=20

5.以下哪个能实时监测到输入框值的变化?

A、input事件

B、change事件

        选择A

五、XMLHttpRequest

1.基础使用

(1)AJAX是浏览器与服务器通信的技术,采用XMLHttpRequest对象的相关代码

(2)axios是对XHR相关的代码进行了封装,让我们只关心传递的接口参数

(3)学习XHR也是了解axios的内部与服务器交互过程的真正原理

语法如下:

const xhr = new XMLHttpRequest()
xhr.open('请求方法', '请求url网址')
xhr.addEventListener('loadend', () => {// 响应结果console.log(xhr.response)
})
xhr.send()

六、同步代码与异步代码

1.同步代码:

逐行执行,需要原地等待结果后,才能继续向下执行
2.异步代码:

调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成过后触发一个回调函数

const result = 0 + 1
console.log(result)
setTimeout(() => {
console.log(2)
}, 2000)
document.querySelector('.btn').addEventListener('click', () => {
console.log(3)
})
document.body.style.backgroundColor = 'pink'
console.log(4)

###结果是1,4,2,,点击一次按钮打印一次3

总结:(1)JS中有哪些异步代码?
setTimeout、setInterval、事件、Ajax

        (2)异步代码用什么接受结果?
用回调函数

七、回调函数地狱

1.概念:
在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱

2.缺点:

可读性差,异常无法捕获,耦合性严重,牵一发动全身

八、Promise-链式调用

1.概念:

依靠 then() 方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束

2.细节:
then() 回调函数中的返回值,会影响新生成的 Promise 对象最终状态和结果

3.优点:
通过链式调用,解决回调函数嵌套问题

总结:
(1)什么是Promise的链式调用?
使用then方法返回新的Promise对象特性,一直串联下去

(2)then回调函数,return的值回传递给那哪里?

传递给then方法生成的新Promise对象

(3)Promise链式调用有什么作用?

解决回调函数嵌套问题

九、解决回调函数地狱

方法:每个 Promise 对象中管理一个异步任务,用 then 返回 Promise 对象,串联起来

核心代码:

let pname = ''
// 1. 得到-获取省份Promise对象
axios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {pname = result.data.list[0]document.querySelector('.province').innerHTML = pname// 2. 得到-获取城市Promise对象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. 得到-获取地区Promise对象return axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})
}).then(result => {console.log(result)const areaName = result.data.list[0]document.querySelector('.area').innerHTML = areaName
})

十、async函数和await

1.概念:
在 async 函数内,使用 await 关键字取代 then 函数,等待获取 Promise 对象成功状态的结果值

2.方法:

使用 async 和 await 解决回调地狱问题

3.核心代码:

async function getData() {// 2. await等待Promise对象成功的结果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/area', params: { pname, cname }})const areaName = aObj.data.list[0]document.querySelector('.province').innerHTML = pnamedocument.querySelector('.city').innerHTML = cnamedocument.querySelector('.area').innerHTML = areaName
}getData()

十一、async函数和await捕获错误

1.try 和 catch 的作用:语句标记要尝试的语句块,并指定一个出现异常时抛出的响应

try {// 要执行的代码
} catch (error) {// error 接收的是,错误消息/

2.尝试把代码中 url 地址写错,运行观察 try catch 的捕获错误信息能力

总结:try和catch有什么作用?(捕获异常)
捕获同步流程的代码报错信息

十二、事件循环

1.概念:
执行代码和收集异步任务的模型,在调用栈空闲,反复调用任务队列里回调函数的执行机制,就叫事件循环

总结:
(1)什么是事件循环?
执行代码和收集异步任务,在调用栈空闲时,反复调用任务队列里的回调执行机制

(2)为什么有事件循环?
JavaScript是单线程的,为了不阻塞JS引擎,设计执行代码的模型

(3)JavaScript内代码是如何执行的?
执行同步代码,遇到异步代码交给宿主浏览器环境执行

十三、事件循环练习

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()

打印结果是?
1  5   3  2  4  点击一次document就会执行一次打印6

十四、宏任务与微任务

1.异步任务划分为了

  • 宏任务:由浏览器环境执行的异步代码

  • 微任务:由 JS 引擎环境执行的异步代码

2.输出结果

/*** 目标:阅读并回答打印的执行顺序
*/
console.log(1)
setTimeout(() => {console.log(2)
}, 0)
const p = new Promise((resolve, reject) => {resolve(3)
})
p.then(res => {console.log(res)
})
console.log(4)

注意:宏任务每次在执行同步代码时,产生微任务队列,清空微任务队列任务后,微任务队列空间释放!

下一次宏任务执行时,遇到微任务代码,才会再次申请微任务队列空间放入回调函数消息排队

即:一个宏任务包含微任务队列,他们之间是包含关系,不是并列关系

总结:
(1)什么是宏任务?

        浏览器执行的异步代码 例如:JS 执行脚本事件,setTimeout/setInterval,AJAX请求完成事件,用户交互事件等
(2)什么是微任务?

        JS 引擎执行的异步代码 例如:Promise对象.then()的回调
(3)JavaScript内代码如何执行?

        执行第一个 script 脚本事件宏任务,里面同步代码 遇到 宏任务/微任务 交给宿主环境,有结果回调函数进入对应队列 当执行栈空闲时,清空微任务队列,再执行下一个宏任务,从1再来

十五、事件循环经典面试题目

// 目标:回答代码执行顺序
console.log(1)//1
setTimeout(() => {//宏任务console.log(2)//5const p = new Promise(resolve => resolve(3))//6(宏中微)p.then(result => console.log(result))
}, 0)
const p = new Promise(resolve => {setTimeout(() => {//宏任务console.log(4)//7}, 0)resolve(5)//3
})
p.then(result => console.log(result))//微任务
const p2 = new Promise(resolve => resolve(6))//4
p2.then(result => console.log(result))//微任务
console.log(7)//2

答案:1  7  5  6  2  3  4 

十六、Promise.all静态方法

1.概念:
合并多个 Promise 对象,等待所有同时成功完成(或某一个失败),做后续逻辑

2.语法:
const p = Promise.all([Promise对象, Promise对象, ...])
p.then(result => {
// result 结果: [Promise对象成功结果, Promise对象成功结果, ...]
}).catch(error => {
// 第一个失败的 Promise 对象,抛出的异常对象
})

总结:
什么时候使用Promise.all ?

        合并多个Promise对象并等待所有同时成功的结果,如果有一个报错就会最终为失败状态,当需要同时渲染多个接口数据同时到网页上使用。

http://www.xdnf.cn/news/1416007.html

相关文章:

  • 在.NET标准库中进行数据验证的方法
  • Java视觉跟踪入门:使用OpenCV实现实时对象追踪
  • 【开题答辩全过程】以 基于php的校园兼职求职网站为例,包含答辩的问题和答案
  • 【Android】使用Handler做多个线程之间的通信
  • 【Flask】测试平台开发,应用管理模块实现-第十一篇
  • 【lucene核心】impacts的由来
  • 旧物回收小程序:科技赋能,开启旧物新生之旅
  • 山东省信息技术应用创新开展进程(一)
  • 《C++进阶之STL》【红黑树】
  • OS+MySQL+(其他)八股小记
  • 【macOS】垃圾箱中文件无法清理的常规方法
  • 应用平台更新:可定制目录、基于Git的密钥管理与K8s项目自动化管理
  • Qt中的信号与槽机制的主要优点
  • LeetCode 142. 环形链表 II - 最优雅解法详解
  • 阿里云代理商:轻量应用服务是什么?怎么用轻量应用服务器搭建个人博客?
  • Linux性能调试工具之ftrace
  • JSP 输出语法全面解析
  • 制造业生产线连贯性动作识别系统开发
  • MCP SDK 学习二
  • 【开题答辩全过程】以 基于Java的网络购物平台设计与实现为例,包含答辩的问题和答案
  • 集合-单列集合(Collection)
  • Docker中使用Compose配置现有网络
  • Ubuntu 中复制粘贴快捷键
  • LeeCode 37. 解数独
  • 【嵌入式】【电机控制】基础知识列表
  • PS自由变换
  • Dreamore AI-解读并描绘你的梦境
  • ARM裸机开发(基础汇编指令)Day02
  • 【AI智能体】LLM记账智能体+MCP服务-实现步骤与效果展示
  • 分布式锁和分布式事务