国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > JS > 正文

如何解決js函數(shù)防抖、節(jié)流出現(xiàn)的問題

2024-05-06 16:52:19
字體:
供稿:網(wǎng)友

React中使用防抖函數(shù)和節(jié)流函數(shù)

在React事件調(diào)用時,React傳遞給事件處理程序是一個合成事件對象的實例。SyntheticEvent對象是通過合并得到的。 這意味著在事件回調(diào)被調(diào)用后,SyntheticEvent 對象將被重用并且所有屬性都將被取消。 這是出于性能原因。 因此,您無法以異步方式訪問該事件。React合成事件官方文檔

所以在用防抖或節(jié)流函數(shù)封裝時,異步方式訪問事件對象出現(xiàn)問題。解決的方法如下:

方法一:調(diào)用合成事件對象的persist()方法 event.persist && event.persist() //保留對事件的引用

方法二:深拷貝事件對象 const event = e && {...e} //深拷貝事件對象

function debounce(func, wait=500) {let timeout; // 定時器變量return function(event){clearTimeout(timeout); // 每次觸發(fā)時先清除上一次的定時器,然后重新計時event.persist && event.persist() //保留對事件的引用//const event = e && {...e} //深拷貝事件對象timeout = setTimeout(()=>{func(event)}, wait); // 指定 xx ms 后觸發(fā)真正想進行的操作 handler};}

防抖debounce

防抖 Debounce 多次觸發(fā),只在最后一次觸發(fā)時,執(zhí)行目標函數(shù)。

函數(shù)防抖就是,延遲一段時間再執(zhí)行函數(shù),如果這段時間內(nèi)又觸發(fā)了該函數(shù),則延遲重新計算。

應(yīng)用場景

(1)通過監(jiān)聽某些事件完成對應(yīng)的需求,比如:

通過監(jiān)聽 scroll 事件,檢測滾動位置,根據(jù)滾動位置顯示返回頂部按鈕

通過監(jiān)聽 resize 事件,對某些自適應(yīng)頁面調(diào)整DOM的渲染(通過CSS實現(xiàn)的自適應(yīng)不再此范圍內(nèi))

通過監(jiān)聽 keyup 事件,監(jiān)聽文字輸入并調(diào)用接口進行模糊匹配

(2)其他場景

表單組件輸入內(nèi)容驗證

防止多次點擊導(dǎo)致表單多次提交

簡單實現(xiàn)

function debounce(fn, wait) {let treturn () => {let context = thislet args = argumentsif (t) clearTimeout(t)t= setTimeout(() => {fn.apply(context, args)}, wait)}}

完整實現(xiàn)

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中調(diào)用方法

this.handleGetCustomerNameList = debounce(this.handleGetCustomerNameList.bind(this), 500);

節(jié)流 throttle

節(jié)流:函數(shù)間隔一段時間后才能再觸發(fā),避免某些函數(shù)觸發(fā)頻率過高,比如滾動條滾動事件觸發(fā)的函數(shù)。

### 簡單實現(xiàn)function throttle (fn, wait, mustRun) {let start = new Date()let timeoutreturn () => {// 在返回的函數(shù)內(nèi)部保留上下文和參數(shù)let context = thislet args = argumentslet current = new Date()clearTimeout(timeout)let remaining = current - start// 達到了指定觸發(fā)時間,觸發(fā)該函數(shù)if (remaining > mustRun) {fn.apply(context, args)start = current} else {// 否則wait時間后觸發(fā),閉包保留一個timeout實例timeout = setTimeout(fn, wait);}}}

完整實現(xiàn)

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中調(diào)用方法

this.handleGetCustomerNameList = throttle (this.handleGetCustomerNameList.bind(this), 500);

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持VeVb武林網(wǎng)。


注:相關(guān)教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 托克托县| 垣曲县| 宜都市| 花垣县| 安远县| 大名县| 合阳县| 石台县| 昭平县| 宜州市| 安化县| 汝州市| 林西县| 娱乐| 安溪县| 禹城市| 新巴尔虎右旗| 崇阳县| 天水市| 治多县| 邳州市| 万年县| 宁明县| 巴南区| 玉田县| 六安市| 九龙县| 江城| 新沂市| 垣曲县| 红河县| 合川市| 广州市| 图们市| 荃湾区| 鄂州市| 镇康县| 泽州县| 株洲市| 弋阳县| 抚州市|