React中使用防抖函数和节流函数
在React事件调用时,React传递给事件处理程序是一个合成事件对象的实例。SyntheticEvent对象是通过合并得到的。 这意味着在事件回调被调用后,SyntheticEvent 对象将被重用并且所有属性都将被取消。 这是出于性能原因。 因此,您无法以异步方式访问该事件。React合成事件官方文档
所以在用防抖或节流函数封装时,异步方式访问事件对象出现问题。解决的方法如下:
方法一:调用合成事件对象的persist()方法 event.persist && event.persist() //保留对事件的引用
方法二:深拷贝事件对象 const event = e && {...e} //深拷贝事件对象
function debounce(func, wait=500) { let timeout; // 定时器变量 return function(event){ clearTimeout(timeout); // 每次触发时先清除上一次的定时器,然后重新计时 event.persist && event.persist() //保留对事件的引用 //const event = e && {...e} //深拷贝事件对象 timeout = setTimeout(()=>{ func(event) }, wait); // 指定 xx ms 后触发真正想进行的操作 handler }; }
防抖debounce
防抖 Debounce 多次触发,只在最后一次触发时,执行目标函数。
函数防抖就是,延迟一段时间再执行函数,如果这段时间内又触发了该函数,则延迟重新计算。
应用场景
(1)通过监听某些事件完成对应的需求,比如:
通过监听 scroll 事件,检测滚动位置,根据滚动位置显示返回顶部按钮
通过监听 resize 事件,对某些自适应页面调整DOM的渲染(通过CSS实现的自适应不再此范围内)
通过监听 keyup 事件,监听文字输入并调用接口进行模糊匹配
(2)其他场景
表单组件输入内容验证
防止多次点击导致表单多次提交
简单实现
function debounce(fn, wait) { let t return () => { let context = this let args = arguments if (t) clearTimeout(t) t= setTimeout(() => { fn.apply(context, args) }, wait) } }
完整实现
function debounce(func, wait, immediate) { let time; let debounced = function() { let context = this; if(time) clearTimeout(time); if(immediate) { let callNow = !time; if(callNow) func.apply(context, arguments); time = setTimeout( ()=>{time = null} //见注解 , wait) } else { time = setTimeout( ()=>{func.apply(context, arguments)} , wait) } }; debounced.cancel = function() { clearTimeout(time); time = null }; return debounced } // underscore.js debounce // // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. _.debounce = function(func, wait, immediate) { var timeout, args, context, timestamp, result; // 处理时间 var later = function() { var last = _.now() - timestamp; if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); // 10ms 6ms 4ms } else { timeout = null; if (!immediate) { result = func.apply(context, args); if (!timeout) context = args = null; } } };
react中调用方法
this.handleGetCustomerNameList = debounce(this.handleGetCustomerNameList.bind(this), 500);
节流 throttle
节流:函数间隔一段时间后才能再触发,避免某些函数触发频率过高,比如滚动条滚动事件触发的函数。
### 简单实现 function throttle (fn, wait, mustRun) { let start = new Date() let timeout return () => { // 在返回的函数内部保留上下文和参数 let context = this let args = arguments let current = new Date() clearTimeout(timeout) let remaining = current - start // 达到了指定触发时间,触发该函数 if (remaining > mustRun) { fn.apply(context, args) start = current } else { // 否则wait时间后触发,闭包保留一个timeout实例 timeout = setTimeout(fn, wait); } } }
完整实现
function throttle(func, wait, options) { let time, context, args, result; let previous = 0; if (!options) options = {}; let later = function () { previous = options.leading === false ? 0 : new Date().getTime(); time = null; func.apply(context, args); if (!time) context = args = null; }; let throttled = function () { let now = new Date().getTime(); if (!previous && options.leading === false) previous = now; let remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0 || remaining > wait) { if (time) { clearTimeout(time); time = null; } previous = now; func.apply(context, args); if (!time) context = args = null; } else if (!time && options.trailing !== false) { time = setTimeout(later, remaining); } }; return throttled; } // underscore.js throttle // Returns a function, that, when invoked, will only be triggered at most once // during a given window of time. Normally, the throttled function will run // as much as it can, without ever going more than once per `wait` duration; // but if you'd like to disable the execution on the leading edge, pass // `{leading: false}`. To disable execution on the trailing edge, ditto. _.throttle = function(func, wait, options) { var context, args, result; var timeout = null; var previous = 0; if (!options) options = {}; var later = function() { previous = options.leading === false ? 0 : _.now(); timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; }; return function() { var now = _.now(); if (!previous && options.leading === false) previous = now; var remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } return result; }; };
react中调用方法
this.handleGetCustomerNameList = throttle (this.handleGetCustomerNameList.bind(this), 500);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
js,函数,防抖,节流
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]