课程名称: JS-Web-API-Ajax、存储与节流防抖
课程章节:Javascript面试课
课程讲师: 双越
课程内容:
🌈JS-Web-API-Ajax
学习课程之前,我们先来看一下这节会遇到哪些面试题? 1、手写一个简易的Ajax 2、跨域常用的实现方式? 接下来,看看知识点吧
2、状态码
xhr.readyState
0 - UNSET尚未调用open方法
1 - OPENED open方法已被调用
2 - HEADERS_RECEIVED send方法已被调用,header已被接收
3 - LOADING下载中,responseText已有部分内容
4 - DONE下载完成
xhr.status
·2xx - 表示成功处理请求,如200
·3xx - 需要重定向,浏览器直接跳转,如301 302 304
·4xx - 客户端请求错误,如404 403
·5xx - 服务器端错误
3、跨域:同源策略,跨域解决方案
同源策略
◆ajax请求时,浏览器要求当前网页和server必须同源(安全)
◆同源:协议、域名、端口,三者必须一致
◆前端:http:/a.com:8080l;server:https:/b.com/api/xxx
加载图片csss可无视同源策略
◆<img src=跨域的图片地址/>
◆<link href=跨域的css地址/>
◆<script src=跨域的js地址></script>
◆<img/>可用于统计打点,可使用第三方统计服务
◆<link/><script>可使用CDN,CDN一般都是外域
◆<script>可实现JSONP
跨域
◆所有的跨域,都必须经过server端允许和配合
◆未经server端允许就实现跨域,说明浏览器有漏洞,危险信号
最后看看面试题的答案吧:
1、手写一个简易的 ajax
function ajax(url) { const p = new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { resolve( JSON.parse(xhr.responseText) ) } else if (xhr.status === 404 || xhr.status === 500) { reject(new Error('404 not found')) } } } xhr.send(null) }) return p } const url = '/data/test.json' ajax(url) .then(res => console.log(res)) .catch(err => console.error(err))
2、跨域的常用的实现方式
JSONP CORS
前端:老方法;JSONP
现在;Vue vue.config.js 设置 devserve
后端:设置CORS 设置response
🌈存储与节流防抖
学习课程之前,我们先来看一下这节会遇到哪些面试题?
◆描述cookie localStorage sessionStorage区别
接下来,看看知识点吧
1、cookie
◆本身用于浏览器和server通讯
◆被”借用”到本地存储来
◆可用document.cookie='...'来修改
cookie的缺点
◆存储大小,最大4KB
◆http请求时需要发送到服务端,增加请求数据量
◆只能用document.cookie='.'来修改,太过简陋
2、localStorage和sessionStorage
◆HTML5专门为存储而设计,最大可存5M
◆API简单易用setltem getltem
◆不会随着http请求被发送出去
◆localStorage数据会永久存储,除非代码或手动删除
◆sessionStorage数据只存在于当前会话,浏览器关闭则清空
一般用localStorage会更多一些
3、手写防抖
◆监听一个输入框的,文字变化后触发change事件
◆直接用keyup事件,则会频发触发change事件
◆防抖:用户输入结束或暂停时,才会触发change事件
<input type="text" id="input1">
const input1 = document.getElementById('input1') let timer = null input1.addEventListener('keyup',function(){ if(timer){ clearTimeout(timer) } timer = setTimeout(()=>{ // 模拟触发 change 事件 console.log(input1.value); // 清空定时器 timer = null },500) })
对防抖函数进行封装:
const input1 = document.getElementById('input1') function debounce (fn,delay = 500){ // timer 是闭包中的 let timer = null return function(){ if(timer){ clearTimeout(timer) } timer = setTimeout( ()=> { fn.apply(this,arguments) timer = null },delay) } } input1.addEventListener('keyup',debounce(function(e){ console.log(e); console.log(input1.value); }))
4、手写节流
◆拖拽一个元素时,要随时拿到该元素被拖拽的位置
◆直接用drag事件,则会频发触发,很容易导致卡顿
◆节流:无论拖拽速度多快,都会每隔100ms触发一次
<style> #div1 { border: 1px solid #ccc; width: 200px; height: 100px; } </style> <div id="div1" draggable="true">可拖拽</div>
const div1 = document.getElementById('div1') let timer = null div1.addEventListener('drag', function (e) { if(timer){ return } timer = setTimeout( () => { console.log(e.offsetX, e.offsetY); timer = null },100) })
对节流函数进行封装:
const div1 = document.getElementById('div1') function jieliu (fn,delay = 100){ let timer = null return function(){ if(timer){ return } timer = setTimeout ( () => { fn.apply(this,arguments) timer = null },delay) } } div1.addEventListener('drag',jieliu(function(e){ console.log(e.offsetX,e.offsetY); },200))