当某个方法需要被多次触发但是又不能太频繁时需要用到防抖节流
防抖
例如 每次输入都会触发change事件,但我们又不希望触发这么频繁时
<Input onChange={this.onChange} />
onChange = ({target:{value}})=>{
console.log(value)
}
第一步:增加一个定时器 当持续输入时定时器在输入过程中被清除 输入停止500毫秒后定时器执行并执行方法打印出数据
let timer = null
onChange = ({target:{value}})=>{
if(timer) clearTimeout(timer)
timer = setTimeout(() => {
console.log(value)
}, 500);
}
第二步:将此方法抽离出来 创建一个 tools.js 文件
因为变量作用域问题,所以需要使用闭包将变量初始化,且因为闭包的变量内存不会被回收,导致内存泄漏问题因此将清除定时器后将变量重置为null 下次执行时将销毁变量重新创建
注: arguments 作用是将函数传递过来的参数不需形参接收 arguments直接获取为数组形式
例如
function show() {
console.log( arguments ); // [1,2,3,4,5]
}
show(1,2,3,4,5);
将需要执行方法从外边传进来 定时器时间也当参数传
export const debounce = (fn,wait = 200) => {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
fn(arguments)
}, wait)
}
}
最后:调用方法
import { debounce2 } from '../utils/tool'
<Input onChange={debounce(this.onChange,2000)} />
onChange = ({target:{value}})=>{
console.log(value)
}
Vue2中稍作修改
<input @input="onChange" />
import { debounce2 } from '../utils/tool'
export default {
name: 'home',
methods: {
onChange: debounce2((params) => {
const { target: { value } } = params[0]
console.log(value)
}, 1000)
}
}
看似可以运行实际闭包原因this指针指向不对,所以最后将this指针修改
最终方法
tool.js
onChange: debounce(function (params) {
console.log(params)
const { target: { value } } = params
console.log(value, this)
}, 1000)
vue 页面
import { debounce } from '../utils/tool'
export const debounce = (fn, wait = 200) => {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
}
节流
与防抖方法一致稍作修改
tool.js
export const throttle = (fn, delay) => {
let curTime = Date.now()
return function () {
let nowTime = Date.now()
if (nowTime - curTime >= delay) {
curTime = Date.now()
return fn(arguments)
}
}
}
vue
onChange: throttle(function (params) {
console.log(params)
const { target: { value } } = params
console.log(value, this)
}, 1000)
以上是原理 也可以用现成的 lodash
npm install lodash -s
import throttle from 'lodash/throttle'
用法与上方一致 且方法后多一个配置项
leading=false 指定在延迟开始前调用。
maxWait 允许被延迟的最大值
trailing=true 指定在延迟结束后调用