解读
函数节流(throttle),指的是某个函数在一定时间间隔内(例如 3 秒)只执行一次,在这 3 秒内产生函数调用请求直接无视,也不会延长时间间隔。3 秒间隔结束后第一次遇到新的函数调用会触发执行,然后在这新的 3 秒内依旧无视新的函数调用请求,以此类推。
快速记忆:安安静静地做好这一件事,不管你怎么打扰。
场景
被频繁调用的场景。如果有大量计算,频繁操作 DOM,资源加载等行为,可能会导致 UI 卡顿(线程阻塞),严重会导致浏览器奔溃。
- 监听 Window 对象的
resize、scroll等事件; - 拖拽监听
mousemove事件; - 文字输入时,对字符串处理或实时搜索;
- ...
自我实现
- 定时器。
- 时间戳。记录上次执行的时间戳,然后每次触发事件执行回调,回调中判断当前时间戳距离上次时间戳的间隔是否达到时间差,如果达到则执行,并更新上次执行的时间戳,如此循环。
// 0.1.1/throttle.js
/**
*
* @param {Function} callback 回调函数
* @param {Number} wait 间隔时间
*
* @return {Function} 节流函数
*/
function throttle(callback, wait = 3000) {
let timer = null;
let startTime;
return function () {
const ctx = this;
const args = arguments;
const now = +new Date();
if (startTime && now < startTime + wait) {
clearTimeout(timer);
timer = setTimeout(function () {
startTime = now;
callback.apply(ctx, args);
}, wait);
} else {
startTime = now;
callback.apply(ctx, args);
}
}
}
网页使用
// 0.1.1/throttle.page.js
const body = document.querySelector('body');
const btn = document.createElement('div');
btn.style = 'cursor: pointer; padding: 10px; background:red; border-radius: 5px; text-align: center; color:#fff;';
btn.innerHTML = '函数节流默认 3 秒';
body.append(btn);
function callback() {
console.log('pr');
}
btn.addEventListener('click', throttle(callback));
React.js
import React from 'react';
import { throttle } from './throttle';
// 使用
export default class ThrottleInReact extends React.Component {
constructor() {
super();
this.change = throttle(e => {
console.log(e.target.value);
}, 1000);
}
onWindowResize = () => {
console.log('resize');
}
onRemoveWindowResize = () => {
console.log('remove resize');
}
handleChange = e => {
e.persist();
this.change(e);
}
render() {
return (
<input onChange={this.handleChange} />
)
}
componentDidMount() {
window.addEventListener('resize', throttle(this.onWindowResize, 60));
}
componentWillUnmount() {
window.removeEventListener('resize', throttle(this.onRemoveWindowResize, 60));
}
}
你可以
文末

