js的防抖与节流
防抖(debounce)
在函数需要频繁触发时,只有当有足够空闲的时间时,才执行一次。就好像在百度搜索时,每次输入之后都有联想词弹出,这个控制联想词的方法就不可能是输入框内容一改变就触发的,他一定是当你结束输入一段时间之后才会触发。
节流(thorttle)
预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。就好像你在淘宝抢购某一件限量热卖商品时,你不断点刷新点购买,可是总有一段时间你点上是没有效果,这里就用到了节流,就是怕点的太快导致系统出现bug。
区别
在发生持续触发事件时,防抖设置事件延迟并在空闲时间去触发事件,而节流则是隔一定的时间触发一次。
原生JavaScript轮播图的节流
原生JavaScript轮播图的节流是为了防止轮播图在不断的点击的操作下,造成内容跑飞与错位的情况。
CSS部分
.lunbo { /* slideshow */ 202px; height: 188px; margin: 100px auto; background-color: hotpink; } .box { /* slideshow的主窗口 */ border: 1px solid black; 200px; height: 186px; position: relative; } ul { /* 所有图片的列表 */ margin: 0; padding: 0; list-style: none; position: absolute; } li { /* 内含img */ float: left; } button { /* 滑动按钮 */ margin: 0; padding: 0; text-align: center; 40px; height: 20px; line-height: 20px; font-size: 16px; border-radius: 5px; } .btnL { /* left按钮 */ position: absolute; top: 83px; left: 0; } .btnR { /* right按钮 */ position: absolute; top: 83px; right: 0; }
HTML部分
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="./effect.css"> </head> <body> <div class="lunbo"> <div class="box"> <ul> <li><img src="./image/01.jpg" alt=""></li> <li><img src="./image/02.jpg" alt=""></li> <li><img src="./image/03.jpg" alt=""></li> <li><img src="./image/04.jpg" alt=""></li> <li><img src="./image/05.jpg" alt=""></li> <li><img src="./image/06.jpg" alt=""></li> </ul> <button class="btnL">left</button> <button class="btnR">right</button> </div> </div> <script src="./slideshow.js"> </script> </body> </html>
JS部分 节流
var btnL = document.getElementsByClassName("btnL")[0];
var btnR = document.getElementsByClassName("btnR")[0];
var box = document.getElementsByClassName("box")[0];
var ul = document.getElementsByTagName("ul")[0];
var liArr = document.getElementsByTagName("li");
// bool为节流设置开关
var bool = true;
// 将ul的width设置为显示窗口的width*li的数量
ul.style.width = liArr.length * box.offsetWidth + "px"
// 为显示窗口设置溢出隐藏
box.style.overflow = "hidden"
// 合理的显示或隐藏按钮
box.onmouseenter = function() {
btnL.style.display = "block"
btnR.style.display = "block"
};
box.onmouseleave = function() {
btnL.style.display = "none"
btnR.style.display = "none"
};
// 为了整体美观将li限制为显示区域的大小
for (var i; i < liArr.length; i++) {
liArr[i].style.width = box.offsetWidth + "px"
}
btnL.onclick = function() {
if (ul.offsetLeft < 0) {
// 节流的关键在于一个函数只有在大于等于执行周期时才执行,周期内调用不执行.
// 利用开关 在函数执行时关闭再次执行的开关,在函数执行结束的回调中再次开启开关
if (bool) {
bool = false
move(ul, ul.offsetLeft + 200, function fn() {
bool = true
})
// move 是封装的简易缓动框架
}
}
};
btnR.onclick = function() {
if (ul.offsetLeft < ul.offsetWidth)
if (bool) {
bool = false
move(ul, ul.offsetLeft - 200, function fn() {
bool = true
})
}
}
// 简易缓动框架
function move(dom, left, fn) {
// 优化写法先清除dom身上的定时器
// 在有节流的情况下可以不写
clearInterval(dom.timer);
dom.timer = setInterval(function() {
// 获取dom此时所处的位置信息
var css = parseInt(window.getComputedStyle(dom, null).left)
// 设置步长
var need = (left - css) / 10;
need = need > 0 ? Math.ceil(need) : Math.floor(need);
// 判断是继续执行还是结束定时器
if (Math.abs(left - css) <= Math.abs(need)) {
// 闪现到目标位置
dom.style.left = left + "px"
clearInterval(dom.timer);
if (fn) {
fn()
}
} else {
// 缓动中
dom.style.left = css + need + "px"
}
}, 100)
}
以上纯属个人看法,如有错误,欢迎大家指出。