住房和城鄉(xiāng)建設(shè)部政務(wù)服務(wù)門戶網(wǎng)站網(wǎng)頁分析工具
前端防抖和節(jié)流
概述
防抖: 防止抖動,個人字面理解此處防的不是頁面的抖動,而是用戶手抖。為了防止用戶快速且頻繁的觸發(fā)事件而導(dǎo)致多次執(zhí)行事件函數(shù),這樣的場景有很多,比如監(jiān)聽滾動、鼠標(biāo)移動事件onmousemove、頻繁點擊表單的提交按鈕等等。
節(jié)流: 節(jié)約流量,為了節(jié)約流量,頁面在一個時間周期內(nèi),只觸發(fā)一次動作。所以節(jié)流的目的時稀釋函數(shù)的執(zhí)行頻率。
防抖動和節(jié)流本質(zhì)是不一樣的。防抖動是多次觸發(fā)但只會執(zhí)行一次,節(jié)流是多次觸發(fā)但周期內(nèi)只會執(zhí)行一次
防抖實現(xiàn)
<html><body><input type="button" id = "btn" value="提交" /><ul id="result"></ul><script>var resultText = ""const print = (text) => {let item = document.createElement('li')item.innerText = textdocument.getElementById("result").appendChild(item)}// 創(chuàng)建debounce防抖函數(shù)const debounce = (func, wait) => {let timeout = null;// 此時func的this指向是window// 如果func內(nèi)部想修改this指向當(dāng)前函數(shù)的調(diào)用者,就必須存儲this,之后借助apply修改func的this指向。// 因此借助閉包緩存調(diào)用者的thislet context = null; let args = null;// 通過定時器延遲執(zhí)行事件函數(shù)let run = () => {timeout = setTimeout(() => {// 通過 apply 修改func的this指向,并讓func獲取真正的事件函數(shù)(即防抖函數(shù)return出來的函數(shù))的參數(shù),之后執(zhí)行funcfunc.apply(context, args);timeout = null}, wait);}// 清除定時器let clean = () => {clearTimeout(timeout);}return function () {context = this; // 誰調(diào)用函數(shù)(這里的函數(shù)是防抖函數(shù)return出來的函數(shù)),this就指向誰。args = arguments; // arguments 是一個對應(yīng)于傳遞給函數(shù)的參數(shù)的類數(shù)組對象,可以獲取函數(shù)的參數(shù)(這里的函數(shù)是防抖函數(shù)return出來的函數(shù))。console.log(args)if (timeout) {print('重置定時器');clean();run();} else {print('開啟新的定時器');run();}}}// 要執(zhí)行的事件函數(shù)const handleSubmit = (e) => {print('提交表單', e);}const fn1 = debounce(handleSubmit, 1500)document.getElementById("btn").addEventListener("click", fn1)</script>
</body></html>
節(jié)流實現(xiàn)
<html><body><input type="button" id="btn" value="提交" /><ul id="result"></ul><script>var resultText = ""const print = (text) => {let item = document.createElement('li')item.innerText = textdocument.getElementById("result").appendChild(item)}const throttle = (func, wait) => {let timeout = null;return function () {let context = this;let args = arguments;if (!timeout) {timeout = setTimeout(() => {timeout = null;func.apply(context, args);}, wait)}}}// 要執(zhí)行的事件函數(shù)const handleSubmit = (e) => {print('提交表單', e);}const fn1 = throttle(handleSubmit, 1500)document.getElementById("btn").addEventListener("click", fn1)</script>
</body></html>