- 本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
- 这是源码共读的第25期,链接:juejin.cn/post/708744…
- 1防抖
定义:事件触发时候,对应函数并不会立即执行,而是会等待规定时间后再执行,如果在规定单位时间内又被触发,这之前触发的所有事件被取消,并重新计时
应用场景:窗口浏览器resize、scroll,按钮提交、表单输入框等
- 基本实现 防抖节流,我们是传入一个函数,后执行,所以我们要内部创建一个函数并返回,在返回函数进行我们相关操作
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
<title>debounce</title>
<style>
#container {
width: 100%;
height: 200px;
line-height: 200px;
text-align: center;
color: #fff;
background-color: #444;
font-size: 30px;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var count = 1;
var container = document.getElementById('container');
function getUserAction() {
console.log(this, event)
container.innerHTML = count++;
};
// container.onmousemove = getUserAction;
container.onmousemove = debounce(getUserAction, 200);
function debounce(func, wait) {
let timer = null;
return _debunce = () => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func();
}, wait);
}
}
</script>
</body>
</html>
2.this、arguments完善 上一版只是实现功能,但是打印this,指向window(因为func()独立函数调用,默认绑定就是window,我们可以通过call,aplly显式指向调用对象,而且事件参数有一个默认event,同时可能还有其他参数,我们可以使用es5-arguments或者使用es6剩余参数都可以
function debounce(func, wait) {
let timer = null;
return _debunce = function (...arg) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, arg);
}, wait);
}
}
现在this和event都正确了
3.增加立即执行和取消功能
立即执行功能了网上版本
function debounce(func, wait, immediate = false) {
let timer = null;
let isInvoke = false;
const _debunce = function (...arg) {
if (timer) clearTimeout(timer);
if (immediate && !isInvoke) {
func.apply(this, arg);
isInvoke = true;
};
timer = setTimeout(() => {
func.apply(this, arg);
isInvoke = false;
}, wait);
}
_debunce.cancel = function () {
if (timer) clearTimeout(timer);
}
return _debunce
}
4.返回结果功能
const debounceFn = debounce(getUserAction, 1000, true, res => {
console.log(res)
});
container.onmousemove = debounceFn;
function debounce(func, wait, immediate = false, cb) {
let timer = null;
let isInvoke = false;
const _debunce = function (...arg) {
if (timer) clearTimeout(timer);
if (immediate && !isInvoke) {
const result = func.apply(this, arg);
isInvoke = true;
if (cb) cb(result)
};
timer = setTimeout(() => {
const result = func.apply(this, arg);
isInvoke = false;
if (cb) cb(result)
}, wait);
}
_debunce.cancel = function () {
if (timer) clearTimeout(timer);
}
return _debunce
}
2.节流
定义:就像水龙头没全部关住,一点点在滴水或者射击游戏技能,不管你单位时间按下多少次,炮弹只会发一次
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
<title>debounce</title>
<style>
#container {
width: 100%;
height: 200px;
line-height: 200px;
text-align: center;
color: #fff;
background-color: #444;
font-size: 30px;
}
</style>
</head>
<body>
<div id="container"></div>
<button id="btn">取消</button>
<script>
var count = 1;
var container = document.getElementById('container');
function getUserAction(event) {
container.innerHTML = count++;
return container.innerHTML
};
// container.onmousemove = getUserAction;
container.onmousemove = throttle(getUserAction, 1000);
function throttle(fn, interval) {
let lastTime = 0;
const _throttle = function(...args) {
const nowTime = Date.now();
const remainTime = interval - (nowTime - lastTime);
if (remainTime <= 0) {
fn.apply(this, args);
lastTime = nowTime;
}
}
return _throttle;
}
</script>
</body>
</html>