Ajax(四)跨域、防抖和节流策略
一、同源策略
1、同源定义
如果两个页面的协议,域名和端口都相同,则两个页面具有相同的源。
2、同源策略定义
同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。
它用于限制一个网站和另一个非同源网站进行资源交互, 增强了网站的安全性, 避免了被攻击的风险
3、同源策略限制了哪些交互
-
无法读取非同源网站的 localStorage, cookie
-
无法访问非同源网站的 DOM
-
无法向非同源网站发送 Ajax 请求
二、跨域
1、定义
同源指的是两个 URL 的协议、域名、端口一致,反之,则是跨域。
出现跨域的根本原因:浏览器的同源策略不允许非同源的 URL 之间进行资源的交互
2、跨域的经典报错
xxx has been blocked by CORS policy
3、浏览器对跨域请求的拦截
浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器拦截,无法被页面获取到!
4、HTML 中的跨域标签
img, script, link, video, iframe… 这些标签可以跨域请求资源
5、实现跨域的常见几种方法
-
JSONP 方案: 利用跨域标签的特性发送 GET 请求获取数据 (缺点: 只能支持 GET 请求)
-
CORS 方案: 服务端处理跨域的一种技术手段, 开发中最为常用
-
代理服务器方案: 前端在本地开发的常用方案, 后面会学习专门的插件
-
手动关闭浏览器的同源策略: 不推荐使用, 安全性很差
6、JSONP的实现原理
-
服务端提供一个函数进行调用, 并传入数据
-
客户端预先准备一个同名函数的声明
-
创建一个 script 标签, 利用 src 属性跨域去获取服务端上的函数调用
注意:
JSONP
只支持GET
数据请求,不支持 POST 请求。JSONP
和 Ajax 之间没有任何关系,不能把JSONP
请求数据的方式叫做 Ajax,因为JSONP
没有用到XMLHttpRequest
这个对象
7、jQuery
中的JSONP
请求
默认情况下, 使用 jquery 发送 jsonp 请求, 会自动携带一个 ?callback=jQuery** 的随机数
$.ajax({
url: 'http://www.liulongbin.top:3006/api/jsonp',
data: {
name: '张三',
age: 10
},
dataType: 'JSONP',
// 更改回调函数的参数(一般很少操作,服务器会识别不了)
// jsonp: 'cdk',
// 更改回调函数的名字
// jsonpCallback: 'foo',
success: function(res) {
console.log(res);
}
})
三、防抖&节流
1、防抖策略(debounce)解释
当一个事件触发时, 不立即执行回调, 延迟一段时间后再执行; 在这段时间内事件再次触发,那么就重新开始计时
2、防抖策略的好处
当我们频繁, 连续触发某个事件时, 只会执行最后一次, 节省了请求资源
3、防抖的应用场景
输入框连续输入字符, 浏览器窗口大小不断调整
案例:
// 先定义一个定时器编号
var timeID = null;
$('button').click(function() {
// 清除原来的定时器
clearTimeout(timeID);
// 再设置一个新的定时器
timeID = setTimeout(() => {
console.log(132);
}, 500)
})
4、缓存搜索的建议列表
-
定义全局缓存对象
-
定义全局缓存对象
// 缓存对象 var cacheObj = {}
-
将搜索结果保存到缓存对象中
- 键就是用户输入的关键字,值就是服务器返回的value
// 渲染建议列表 function renderSuggestList(res) { // ...省略其他代码 // 将搜索的结果,添加到缓存对象中 var k = $('#ipt').val().trim() cacheObj[k] = res }
-
优先从缓存中获取搜索建议
- 在发起请求之前,先判断缓存中是否有数据
// 监听文本框的 keyup 事件 $('#ipt').on('keyup', function() { // ...省略其他代码 // 优先从缓存中获取搜索建议 if (cacheObj[keywords]) { return renderSuggestList(cacheObj[keywords]) } // 获取搜索建议列表 debounceSearch(keywords) })
5、节流
-
定义
顾名思义,可以减少一段时间内事件的触发频率。
-
节流的应用场景
① 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;
② 懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源;
// 定义一个节流阀,默认为打开
var flag = true;
$("button").click(function() {
// 判断当前阀门是否打开
if (flag == false) return;
// 开始执行动画前,先关闭阀门
flag = false;
setTimeout(() => {
console.log(123);
// 动画结束后,打开阀门
flag = true;
}, 500)
})
案例:小天使鼠标跟随效果
$(function() {
//定义一个节流阀,默认打开
var flag = true;
var num = 0;
$(document).mousemove(function(e) {
if (flag == false) return;
//动画开始前关闭
flag = false;
setTimeout(() => {
// 打印鼠标移动次数
console.log(num++);
$('img').css({
left: e.pageX,
top: e.pageY
});
//动画结束后打开
flag = true;
}, 20)
})
})
6、防抖和节流的区别
- 防抖和节流的共同点:
-
都能有效地降低事件触发的频率
-
都能节省资源, 优化性能和用户体验
-
防抖和节流的不同点:
-
防抖在频繁触发事件的情况下, 只有最后一次生效; 节流则是在单位时间内生效一次
-
防抖实现的核心是 “销毁定时器”; 节流实现的核心是 “更新节流阀”
-