Skip to content

JavaScript中的防抖与节流、在react class及hook中使用防抖与节流 - starlog - 博客园 #95

Description

@HenryTSZ

函数防抖:函数被触发后过一段时间再执行,如果在这段时间内又被触发,则重新计时,即将多次高频操作优化为只在最后一次执行。应用场景为用户连续输入,只需要在输入结束后做一次校验即可,比如input搜索或校验。简而言之,就是在input请求时使用防抖。

function debounce(func, ms = 1000) {
let timer; return function (...args) { if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
func.apply(this, args)
}, ms)
}
} // 测试
const task = () => { console.log('run task') }
const debounceTask = debounce(task, 1000)
window.addEventListener('scroll', debounceTask)

函数节流:函数在一段时间内只能被触发一次,如果这段时间内被触发多次,则只有一次生效,即每隔一段时间执行一次,也就是降低频率,将高频操作优化成低频操作。应用场景为滚动条事件或窗口resize事件,通常每隔100-500ms执行一次。简而言之,就是在滚动条请求时使用节流。

function throttle(func, ms = 1000) {
let canRun = true
return function (...args) { if (!canRun) return canRun = false setTimeout(() => {
func.apply(this, args)
canRun = true }, ms)
}
} // 测试
const task = () => { console.log('run task') }
const throttleTask = throttle(task, 1000)
window.addEventListener('scroll', throttleTask)

防抖或节流一般使用:

import debounce from 'lodash/debounce' debounce(()=>search(value), 500)

在类组件中使用防抖或节流:

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { Input } from 'antd';
import throttle from 'lodash/debounce';

class Search extends React.Component {
constructor(props) {
super(props) this.handleSearch = throttle(this.handleOnChange, 200);
}

handleOnChange = (e) => {
  console.log(e.target.value)
}
render() { return ( <Input onChange={this.handleSearch} />

)
}
}

ReactDOM.render( ,
document.getElementById('container'),
);

在函数组件中使用防抖或节流,需要使用useCallback或useRef缓存变量和方法:

import React, { useCallback } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { Input } from 'antd';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';

const Search = () => {

const handleOnChange = (e) => {
console.log(e.target.value)
}
const handleSearch = useCallback(throttle((e) => handleOnChange(e), 500), []) return ()
}

ReactDOM.render(, document.getElementById('container'));

import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { Input } from 'antd';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';

const Search = () => {

const handleOnChange = (e) => {
console.log(e.target.value)
}
const handleSearch = useRef(throttle((e) => handleOnChange(e), 500)).current return ()
}

ReactDOM.render(, document.getElementById('container'));

在函数组件里使用debounce,不使用lodash:

import { useEffect } from 'react'
function useDebounce(fn, delay, dep=[]) {
useEffect(()=>{
let timer;
timer = setTimeout(fn, delay); return ()=>clearTimeout(timer);
}, [...dep]
)
}
export default useDebounce // 调用
useDebounce(()=>search(value), 500, [value])

import { useRef } from 'react'
function useDebounce(fn, delay) {
const timer = useRef(null); return () => {
clearTimeout(timer.current);
timer.current = setTimeout(fn, delay);
}
}
export default useDebounce // 调用
const debounceSearch = useDebounce(() => handleParams(params), 500)
useEffect(()=>{debounceSearch()},[value]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions