为此,我们举个示例代码来了解事件如何频繁的触发: 我们写一个 index.html 文件: 从左边滑到右边就触发了近100次 因为这个例子很简单,所以浏览器完全反应的过来,但假设: 这种在一瞬间(短时间内)对浏览器或服务器造成了过多压力的交互就需要进行优化了,为了解决这个问题,一般有两种解决方案: 他们的目的都是:降低一个函数的触发频率,以提高性能或避免资源浪费。 今天重点讲讲防抖的实现。 防抖的原理就是:你尽管触发事件,但是我一定在事件触发 我们规定 我们根据上一节提到的核心思想,实现第一版代码: 如果我们要使用它,第一节的例子为例: 此时大家可以再次测试一下,事件持续发生时,只有在完全停止2s后,才会触发事件: 写到这里,作为针对部分高频事件的需求来说,已经结束了。我们来看看他的效果: 大家都知道,dom节点在触发事件的时候,this指向它本身,本例中则指向 毕竟经过了一层匿名函数的包裹,this已经指向了window,为了减少影响,我们尝试修正它 解决的this指向问题,我们的函数仍然不够“完美”,JavaScript中,事件处理函数会提供 为了保证它的原汁原味,我们再改第三版: 到此为止,我们在尽可能保留Dom事件原有能力的情况下,给函数加上了防抖效果,它可以解决大部分我们日常开发的防抖问题,但我们需要更“完美” 这个需求就是: 想想这个需求也是很有道理的嘛,那我们加个 再来看下此时他是什么效果: 如果你希望能取消被防抖的事件,我们可以这样写: 我们再来看看效果: 写到这里这个简单的防抖方法就算OK了,它确实还不算完美,如果在改进上有任何建议,不妨在评论区留言吧~ JavaScript专题系列: 另外推荐大家阅读一下我的《前端内功进阶系列》 关于我 其他沉淀 如果您看到了最后,不妨、、关注一下吧!您的三连就是我最大的动力,虚心接受大佬们的批评和指点,共勉!
防抖
目录
一、为什么需要防抖
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <title>debounce</title> <style> #wrapper { width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px; } </style> </head> <body> <div id="wrapper"></div> <script> var count = 1; var oDiv = document.getElementById("wrapper"); function getUserAction() { oDiv.innerHTML = count++; } oDiv.onmousemove = getUserAction; </script> </body> </html>
getUserAction
函数!看如下Gif:
二、防抖的原理
n秒无操作后
才执行。举个例子:3s
为防抖的标准,那么:
三、自己实现一个防抖
3.1 第一版
function debounce(func, wait) { var timer; return function () { clearTimeout(timer) timer = setTimeout(func, wait); } }
oDiv.onmousemove = debounce(getUserAction, 2000);
3.2 第二版
oDiv
,但是在本例中:我们看一下var count = 1; var oDiv = document.getElementById("oDiv"); function getUserAction() { oDiv.innerHTML = count++; console.log('this', this); // 此时输出 Window... } oDiv.onmousemove = debounce(getUserAction, 2000); function debounce(func, wait) { var timer; return function () { clearTimeout(timer) timer = setTimeout(func, wait); } }
function debounce(func, wait) { var timer; return function () { var _this = this; // 记录当前this clearTimeout(timer) timer = setTimeout(function(){ func.apply(_this); //将 func的this改为_this }, wait); } }
第三版
event
对象,我们简称为e。// 使用了 debouce 函数 function getUserAction(e) { console.log(e); // undefined oDiv.innerHTML = count++; };
var count = 1; var oDiv = document.getElementById("oDiv"); function getUserAction(e) { oDiv.innerHTML = count++; console.log('e', e); // MouseEvent } oDiv.onmousemove = debounce(getUserAction, 2000); function debounce(func, wait) { var timer; return function () { var _this = this; // 记录当前this var arg = arguments; // 记录参数 clearTimeout(timer) timer = setTimeout(function () { func.apply(_this, arg); //将 func的this改为_this }, wait); } }
四、防抖进阶
4.1 立即执行
n
秒空白期n
秒空白期置后immediate
参数判断是否是立刻执行。function debounce(func, wait, immediate) { var timer; return function () { var _this = this; var args = arguments; if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时 if (immediate) { // 如果已经执行过,不再执行 var callNow = !timer; // 1. callNow 初始值是 true, 同步立即执行;随后 timer 才开始执行 timer = setTimeout(function(){ timer = null; // wait 期间,timer 是一个 ID 数字,所以 callNow 为 false,func 在此期间永远不会执行 }, wait) // wait 之后,timer 赋值 null,callNow 为 true,func 又开始立即执行。 if (callNow) func.apply(_this, args) } else { timer = setTimeout(function(){ func.apply(_this, args) }, wait); } } }
4.2 添加简单验证
function debounce(func, wait, immediate) { var timer; // 检查函数 if (typeof func !== 'function') { throw new TypeError('Expected a function'); } // 保证wait存在 wait = +wait || 0; const debounced = function () { var _this = this; var args = arguments; if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时 if (immediate) { // 如果已经执行过,不再执行 var callNow = !timer; // 如果不存在定时器,则callNow为true timer = setTimeout(function () { timer = null; // 为了保证之后的时效性,手动添加timer }, wait) // 因为不存在timer,证明是首次执行,所以直接调用 if (callNow) func.apply(_this, args) } else { timer = setTimeout(function () { func.apply(_this, args) }, wait); } } return debounced }
4.3 添加取消事件方法
function debounce(func, wait, immediate) { var timer; // 检查函数 if (typeof func !== 'function') { throw new TypeError('Expected a function'); } // 保证wait存在 wait = +wait || 0; const debounced = function () { var _this = this; var args = arguments; if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时 if (immediate) { // 如果已经执行过,不再执行 var callNow = !timer; // 如果不存在定时器,则callNow为true timer = setTimeout(function () { timer = null; // 为了保证之后的时效性,手动添加timer }, wait) // 因为不存在timer,证明是首次执行,所以直接调用 if (callNow) func.apply(_this, args) } else { timer = setTimeout(function () { func.apply(_this, args) }, wait); } } const cancel = function(){ clearTimeout(timer); timer = null; } const pending = function(){ return timer !== undefined; } debounced.cancel = cancel; debounced.pending = pending; return debounced }
参考
写在最后
前端专项进阶系列的第二篇文章
,希望它能对大家有所帮助,如果大家有什么建议,可以在评论区留言,能帮到自己和大家就是我最大的动力!
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算