Repository navigation
Expand file tree
/
Copy path065函数节流和函数去抖
More file actions
189 lines (147 loc) · 5.55 KB
/
Copy path065函数节流和函数去抖
File metadata and controls
189 lines (147 loc) · 5.55 KB
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
一. 函数节流
1. 什么是函数节流
如果用户在一个短的时间内触发非常多次事件绑定程序,如果在这个程序内部绑定了一些DOM操作,高频率的更改就会使浏览器崩溃。
为了防止这种情况,就需要用到函数节流的思想,某些代码不可以在没有间断的情况下连续重复地执行。
eg:
给浏览器绑定一个onresize事件,当用户在将浏览器宽度变大变小的过程中,会一直触发onresize事件。
页面滚动时,滚动到哪有一定的效果,绑定onscroll事件
大部分节流都采用时间做节流,即时间间隔小于多少的不再调用,但同时保证一个最小调用间隔
2. 用定时器来实现函数节流
原理:当我触发一个事件时,先setTimout让这个事件延迟一会再执行,如果在这个时间间隔内又触发了事件,那我们就clear掉原来的定时器,
再setTimeout一个新的定时器延迟一会执行,就这样。
function throttle(method, context) {
clearTimeout(method.tId);//将定时器存在method.tId里
method.tId = setTimeout(function(){
method.call(context);//确保函数在正确的环境中执行
}, 100);//两次函数调用之间的间隔至少为100ms
}
function myFunc(){
var div = document.getElementById("myDiv");
div.style.height = div.offsetWidth + "px";//实现使一个div的高度等于其宽度
}
window.onresize = function(){
throttle(myFunc);//不直接调用myFunc,而是通过throttle来调用myFunc
}
二. 函数去抖
1. 什么是函数去抖
当一个函数在在一定的间隔内没有被调用时,才开始执行被调用的方法。
例如:用户在输入一段文字时,对文字进行处理,监听文字改变事件,每一次改变都会调用一次回调函数,但是想要的功能只是在用户输入停下来的时候才去
执行回调函数。
function debounce(func, wait, immediate) {
var timeout, result;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if(!immediate) {
result = func.apply(context, args);
}
}
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if(callNow) {
result = func.apply(context, args);
}
return result;
}
}
假设immediate == true:
首次调用debounce(func,wait,immediate),callNow = true,执行func函数;
第二次调用debounce(func,wait,immediate)
若间隔时间 < wait,callNow == false,不执行func函数
若间隔时间 > wait,callNow == true,执行func函数
-----------------------------------------------------------------------------------------------------------
2019.03.31
在线测试:http://demo.nimius.net/debounce_throttle/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>防抖测试</title>
<style type="text/css">
div {
width: 200px;
height: 300px;
background: red;
overflow: auto
}
</style>
</head>
<body>
<div id="container">scroll 事件本身会触发页面的重新渲染,
同时 scroll 事件的 handler 又会被高频度的触发,
因此事件的 handler 内部不应该有复杂操作,例如 DOM 操作就不应该放在事件处理中。
针对此类高频度触发事件问题(例如页面 scroll ,屏幕 resize,
监听用户输入等),有两种常用的解决方法,防抖和节流。</div>
<script type="text/javascript">
// 将会包装事件的 debounce 函数
function debounce(fn, delay) {
// 维护一个 timer
let timer = null;
return function() {
// 通过 ‘this’ 和 ‘arguments’ 获取函数的作用域和变量
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
}
};
// 当用户滚动时被调用的函数
function foo() {
console.log('你刚才拖拽了滚动条!!!');
}
// 在 debounce 中包装我们的函数,过 2 秒触发一次
let elem = document.getElementById('container');
console.log('滚动停止后等待两秒钟')
elem.addEventListener('scroll', debounce(foo, 2000));
</script>
</body>
</html>
-------------------------------------------------------------------------------------------------------
节流
var throttle = function(func, delay) {
var prev = Date.now();
return function() {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
}
}
var throttle = fucntion(func, delay) {
var timer = null;
return funtion() {
var context = this;
var args = arguments;
if (!timer) {
timer = setTimeout(function() {
func.apply(context, args);
timer = null;
}, delay);
}
}
}
var throttle = function(func, delay) {
var timer = null;
var startTime = Date.now();
return function() {
var curTime = Date.now();
var remaining = delay - (curTime - startTime);
var context = this;
var args = arguments;
clearTimeout(timer);
if (remaining <= 0) {
func.apply(context, args);
startTime = Date.now();
} else {
timer = setTimeout(func, remaining);
}
}
}