本文摘自PHP中文网,作者coldplay.xixi,侵删。
目录
(免费学习推荐:javascript视频教程)
前言
我们来聊一聊节流――另一个优化函数的思想。
我们还是以移动事件举例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <!DOCTYPE html><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>
<style>
#wrapper {
width: 100%;
height: 140px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
font-size: 30px;
font-weight: bold;
line-height: 140px;
text-align: center;
}
</style></head><body>
<p id= "wrapper" ></p>
<script>
var count = 1;
function moveAction () {
oWrapper.innerHTML = count ++;
}
var oWrapper = document.querySelector( '#wrapper' );
oWrapper.onmousemove = moveAction;
</script></body></html>
|
它的效果是这样:
一、核心和基本实现
节流的原理很简单:如果你持续触发某个事件,特定的时间间隔内,只执行一次。
关于节流的实现,有两种主流的实现方式:
- 时间戳思路
- 定时器思路
1.1 时间戳思路
顾名思义,通过两个时间戳来控制时间间隔,当触发事件的时候:
- 我们取出当前的时间戳
now
; - 然后减去之前执行时的时间戳(首次值为 0 )
prev
; - 如果大
now - prev > wait
,证明时间区间维护结束,执行指定事件,更新prev
;
根据这一思路,我们就可以实现第一版代码了:
1 2 3 4 5 6 7 8 9 10 11 12 | oWrapper.onmousemove = throttle(moveAction, 1000); function throttle(func, wait) {
var _this, arg;
var prev = 0;
return function () {
var now = Date .now();
_this = this;
if (now - prev > wait) {
func.apply(_this, arg);
prev = now;
}
}}
|
来看看借助它,效果是什么样的:
我们可以看到:
- 当鼠标移入的时候,事件立刻执行
- 每过 1s 会执行一次,且移动2.5s会执行2次,意味着动作停止后不会再执行。
1.2 定时器思路
利用定时器来保证间隔时间内事件的触发次数
- 创建定时器
timer
,记录当前是否在周期内; - 判断定时器是否存在,若存在则直接结束,否则执行事件;
wait
时间之后再次执行,并清掉定时器;
当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行,直到定时器执行,然后执行函数,清空定时器,这样就可以设置下个定时器。
1 2 3 4 5 6 7 8 9 10 11 12 | function throttle(func, wait) {
var _this, arg;
var timer;
return function () {
_this = this;
arg = arguments;
if (timer) return ;
timer = setTimeout(() => {
func.apply(_this, arg);
timer = null;
}, wait);
}}
|
来看看借助它,效果是什么样的:
但是,我们可以看到:
- 当鼠标移入的时候,事件不会立刻执行;
- 鼠标定制后
wait
间隔后会执行一次
1.3 两种思路的区别
| 时间戳 | 定时器 |
---|
“起点” | 立即执行 | n 秒后执行 |
“终点” | 停止后不会执行 | 停止会再执行一次 |
二、节流进阶
结合两种思想完成一个可以立即执行,且停止触发后再执行一次的节流方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | var timeout, context, args, result;
var previous = 0;
var later = function () {
previous = + new Date ();
timeout = null;
func.apply(context, args)
};
var throttled = function () {
var now = + new Date ();
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
} else if (!timeout) {
timeout = setTimeout(later, remaining);
}
};
return throttled;}
|
效果演示如下:
我在看代码的时候,我是反复打印数据才理解为什么会这样做,一起加油~
相关免费学习推荐:javascript(视频)
以上就是JavaScript专题之四:节流的详细内容,更多文章请关注木庄网络博客!
相关阅读 >>
javascript专题之四:节流
更多相关阅读请进入《javascript节流》频道 >>
人民邮电出版社
本书对 Vue.js 3 技术细节的分析非常可靠,对于需要深入理解 Vue.js 3 的用户会有很大的帮助。——尤雨溪,Vue.js作者
转载请注明出处:木庄网络博客 » JavaScript专题之四:节流