day22 ajax
概述 :
AJAX (asynchronous javaScript and xml ) 是异步的JavaScript和xml . 它是用于发送http请求的 , 也可以发送异步和同步请求 , 它的特点是可以完成页面的局部刷新功能 ( 在整个页面不刷新的前提下 , 发送对应的请求改变对应的部分的dom ) , 它的核心对象是XMLHTTPRequest ( xhr )
-
是一种服务器和浏览器进行 "通讯" 的技术 ,
可以实现局部刷新 ( 降低了服务器的压力 , 提高了页面渲染速度 , 减少重绘和回流提高用户体验)
-
为什么使用ajax ? - 为了提高用户体验
-
使用了onreadystatechange事件 , 并结合callback回调函数取值来解决异步
-
ajax的同步,会在发送请求时占据主线程 造成阻塞 , 不推荐使用 ( js引擎是单线程的,同步会造成阻塞 )
关键词 :
-
线程 : 线程是进程的最小单位 , JavaScript是单线程的语言 ( 单线程解析 , 渲染线程也是单线程 )
-
进程 : 正在运行的程序
-
同步 : 同一个线程执行 , 会造成同步阻塞 ( 上一个线程没有做完 , 下一个就不能执行 )
-
异步 : 多个线程 ( 上一个线程和这一个线程没有关系 )
请求流程 :
//1.新建请求对象 var xhr=new XMLHttpRequest() //2.设置请求地址和请求方式 xhr.open('get','请求地址') //3.发送请求 xhr.send() //4.监听请求状态的变化 readystate(0-4,0是什么都没做,1准备发送,2发送完成,3发送完成数据准备接收,4数据接收完毕(响应完成),5是错误) xhr.onreadystatechange = ()=>{ //进行判断对应的状态 if(xhr.readyState==4){ //responseText返回的文本是字符串 console.log(xhr.responseText) } }
XMLRequest对象的相关属性及方法
属性 :
-
readyState 状态码
-
status http状态码
-
timeout 超时时间
-
responseText 响应文本
方法 :
-
open() 打开一个请求
-
send() 发送请求
-
setRequestHeader() 设置请求头
-
事件 :
-
onreadystatechange=()=>{}
var xhr = new XMLHttpRequest() // 属性 //1.readyState 对应的xhr对应的状态码(这个状态码只有xhr才有) console.log(xhr.readyState) //2.status http状态码 (只要发送http请求都会有) //取值为100-599 //1开头(表示成功,但是需要后续操作) , // 2开头(数据请求成功 ,一般是200) , // 3开头(重定向,304重新定义方向,就是去了别的页面) , // 4开头(客户端错误,404找不到页面,403访问权限不足) , // 5开头(服务器错误,500) 跟前端无关系 console.log(xhr.status) //3.responseText 响应的文本 console.log(xhr.responseText) //4.responseXML 响应的xml console.log(xhr.responseXML) //responseType 响应类型 console.log(xhr.responseType) //responseURL 响应地址 console.log(xhr.responseURL) // 设置请求的超时事件 console.log(xhr.timeout) // 方法 // 设置请求 open 请求方式,请求地址 xhr.open('get', '请求地址') // 发送请求 可传参,参数是设置给请求体的内容 xhr.send('') // 设置请求头,通过键值对的方式(2个参,都是字符串) xhr.setRequestHeader() // 响应头获取,根据key获取值 xhr.getResponseHeader('Content-type') // 事件 当前状态改变的事件 xhr.onreadystatechange = () => { // 判断readyState为4并且http状态码以2开头 if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) { console.log('世界') } } console.log('你好')
<button>请求数据</button> <ul></ul> <script> // 获取ul let ul = document.querySelector('ul') // 给按钮添加点击事件 document.querySelector('button').onclick = () => { // 创建请求对象 let xhr = new XMLHttpRequest() // 设置请求方式和地址 // get请求传参使用?和&做拼接,第一个前面要加?,多个参数使用&连接 xhr.open('get', 'http://jsonplaceholder.typicode.com/todos') // 发送数据 xhr.send() // 监听状态变化 xhr.onreadystatechange = () => { // 如果状态码都是正常的 if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) { // 那么先将字符串转为对象 let result = JSON.parse(xhr.responseText) // 再遍历进行渲染 result.forEach((item) => { ul.innerHTML += ` <li> id:${item.id} ${item.title} ${item.completed ? '💓' : '💔'} </li> ` }) } } } </script>
// 封装一个get方法 ,url请求地址,params参数(以对象传递),callback对应的处理方式 function get(url, params = {}, callback) { // 如果没有填url就直接报错 if (!url) { throw new Error('url必须填写') } // 创建请求对象 let xhr = new XMLHttpRequest() // 设置请求方式和地址 // 先遍历参数 for (let key in params) { // 判断url地址是否存在?没有就加在前面,有就在前面加& if (!url.includes('?')) { url += `?${key}=${params[key]}` } else { url += `&${key}=${params[key]}` } } xhr.open('get', url) // 发送数据 xhr.send() // 监听状态变化 xhr.onreadystatechange = () => { // 判断是否成功 if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) { // 成功就调用回调函数传递参数 // 先转成对象再传递 callback(JSON.parse(xhr.responseText)) } } }
<nav aria-label="Page navigation"> <ul class="pagination"> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> </ul> </nav> <ul class="content"></ul> <script type="module"> // 导入封装的get方法 import { get } from './00.js' // 获取按钮和显示区域 let lis = document.querySelectorAll('.pagination li a') let ul = document.querySelector('.content') // 给每个按钮添加点击事件 Array.prototype.forEach.call(lis, ((item, index) => { item.onclick = () => { // 调用get方法,传入地址,参数和处理方法进行渲染 get('http://jsonplaceholder.typicode.com/todos', { _limit: 10, _page: index+1 }, (res) => { ul.innerHTML='' res.forEach((item)=>{ ul.innerHTML+= `<li> id:${item.id}, ${item.title}, ${item.completed?'💙':'💚'} </li>` }) }) } })) </script>
<form action="https://jsonplaceholder.typicode.com/posts" method="post"> <input type="text"><br> <input type="password"><br><br> <button type="submit">登录</button> </form> <script> // 获取form表单并添加提交事件 document.forms[0].onsubmit = () => { // 获取input框的内容 let inputs = document.querySelectorAll('input') let uname = inputs[0].value let upwd = inputs[1].value // 创建请求对象 let xhr = new XMLHttpRequest() // 设置请求方式和地址 xhr.open('post', "https://jsonplaceholder.typicode.com/posts") // 设置请求头 xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded') // 发送数据 xhr.send(`uname=${uname}&upwd=${upwd}`) // 监听状态变化 xhr.onreadystatechange = (e) => { // 阻止默认行为 e = e || window.event e.preventDefault() // 判断是否成功 if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) { console.log(xhr.responseText) } } } </script>
// post请求封装 export function post(url, params = {}, callback) { // 判断url地址是否传递,如果没有传递就直接报错 if (!url) { throw new Error('url必须传递') } // 新建请求对象 let xhr = new XMLHttpRequest() // 设置请求方式和地址 xhr.open('post', url) // 设置请求头 xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded') // 数据拼接 let paramsStr = '' for (let key in params) { paramsStr += `&${key}=${params[key]}` } paramsStr = paramsStr.substring(1) // 发送数据 xhr.send(paramsStr) // 监听状态变化 xhr.onreadystatechange = () => { // 成功就调用回调函数传递参数出去 if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) { callback(JSON.parse(xhr.responseText)) } } }
// 封装get和post方法 export const ajax = (url, option, callback) => { //判断是否有传入url,没传直接报错 if (!url) { throw new Error() } //设置一个默认的参数对象(url内的) let defalutOption = { method: 'get', data: {}, contentType: 'application/json', timeout: 3000 } //遍历对象里的key for (let key in option) { //如果默认参数对象里有就用option里的key来替换掉 if (defalutOption[key]) { defalutOption[key] = option[key] } } //新建请求对象 let xhr = new XMLHttpRequest() //如果是get请求 if (defalutOption.method == 'get') { //就先遍历对象再判断url内是否存在'?' for (let key in option) { if (!url.includes('?')) { url += `??{key}=${option[key]}` } else { url += `&${key}=${option[key]}` } } } //设置请求方式和请求地址 xhr.open(defalutOption.method, url) //设置请求头 xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded') //如果是post请求 if (defalutOption.method == 'post') { //数据拼接发送 let optionStr = '' for (let key in defaultOption.data) { optionStr += `&${key}=${defaultOption.data[key]}` } //删除最前面的& optionStr = optionStr.substring(1) //发送请求 xhr.send(optionStr) } else { xhr.send() } //监听状态变化 xhr.onreadystatechange = () => { if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) { callback(JSON.parse(xhr.responseText)) } } }
//抽取post请求和get请求 export const ajax = (url, option) => { //判断是否具备url if (!url) { throw new Error() } //你传什么就改什么 不传为默认值 let defalutOption = { method: 'get', data: {}, contentType: 'application/json', timeout: 3000 } //遍历对象里面key for (let key in option) { //默认的选项里面存在这个key if (defalutOption[key]) { //用option里面对应key的值来替换默认值 defalutOption[key] = option[key] } } //新建请求对象 let xhr = new XMLHttpRequest() //判断是get请求还是post请求 if (defalutOption.method == 'get') { //遍历对象中所有的属性 for (let key in defaultOption.data) { //判断url里面是否存在? 如果没有就加上 if (!url.includes('?')) { url += `?${key}=${defaultOption.data[key]}` } else { url += `&${key}=${defaultOption.data[key]}` } } } xhr.open(defalutOption.method, url) //设置请求头 xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded') //判断是否为post请求 if (defalutOption.method == 'post') { //数据拼接发送 let paramsStr = '' for (let key in defalutOption.data) { paramsStr = defalutOption.data[key] } //删除最前面的& paramsStr = paramsStr.substring(1) //发送请求 xhr.send(paramsStr) } else { //发送请求 xhr.send() } return new Promise((resolve, reject) => { //监听请求状态改变 xhr.onreadystatechange = () => { //判断是否成功 if (xhr.readyState == 4) { //成功调用resolve传递数据 //先转为对象再传递出去 if (/^2\d{2}$/.test(xhr.status)) { resolve(JSON.parse(xhr.responseText)) } if (/^4\d{2}$/.test(xhr.status)) { reject() } } } //如果xhr对象有错也调用reject xhr.onerror = () => { reject() } }) }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)