天天看點

按鈕防抖與節流-vue2

防抖與節流,應用場景有很多,例如:禁止重複送出資料的場景、搜尋框輸入搜尋條件,待輸入停止後再開始搜尋。

防抖

  • 點選button按鈕,設定定時器,在規定的時間内再次點選會重置定時器重新計時,在規定的時間沒有再次點選才執行相關函數。
  • 規定時間内最後一次點選有效。

節流

  • 點選button按鈕,執行相關函數。設定定時器,在規定的時間内連續點選均無效,定時器過後,可以再次點選。
  • 規定時間内可點選一次(第一次點選有效)。

案例-防抖

Vue項目中使用自定義指令實作(按鈕)防抖功能。

應用場景:搜尋框輸入搜尋條件,待輸入停止後再開始搜尋。

/*
*  防抖,規定時間内最後一次點選有效。
*  @param {?Number|300} time - 間隔時間,毫秒
*  @param {Function} fn - 執行函數
*  @param {?String|"click"} event - 事件類型 例:"click"
*  @param {Array} binding.value - [fn,event,time]
*  例:<el-button v-debounce="[resetData,`click`,300]">重新整理</el-button>
*  也可簡寫成:<el-button v-debounce="[resetData]">重新整理</el-button>
*/
// 注冊一個全局自定義指令 `v-debounce`
Vue.directive('debounce', {
  // 當被綁定的元素插入到 DOM 中時……
  inserted: function (el, binding) {
    //binding.value,使用自定義指令v-debounce時填寫的參數
    //解構指派,定義了3個變量,将參數(數組)按順序進行指派
    let [fn, event = "click", time = 300] = binding.value
    let timer
    el.addEventListener(event, () => {
      //預設監聽的事件為click
      //判斷計時器是否存在,存在則清除計時器。重新建立計時器,到時間後執行函數fn
      if(timer){
        clearTimeout(timer)
      }
      timer = setTimeout(() => fn(), time)
    })
  }
})
           

案例-節流

Vue項目中使用自定義指令實作(按鈕)節流功能。

應用場景:click事件,禁止重複送出資料的場景。

/*
*  節流,規定時間内可點選一次(第一次點選有效)。
*  @param {?Number|300} time - 間隔時間,毫秒
*  @param {Function} fn - 執行函數
*  @param {?String|"click"} event - 事件類型 例:"click"
*  @param {Array} binding.value - [fn,event,time]
*  例:<el-button v-throttle="[resetData,`click`,300]">重新整理</el-button>
*  傳遞參數則:<el-button v-throttle="[()=>resetData(param),`click`,300]">重新整理</el-button>
*/
// 注冊一個全局自定義指令 `v-throttle`
Vue.directive('throttle', {
  // 當被綁定的元素插入到 DOM 中時……
  inserted: function(el, binding) {
    //binding.value,使用自定義指令v-throttle時填寫的參數
    //解構指派,定義了3個變量,将參數(數組)按順序進行指派
    let [fn, event = "click", time = 300] = binding.value
    let timer = null;
    el.addEventListener(event, () => {
      //預設監聽的事件為click
      //判斷計時器是否存在,不存在則執行函數fn,建立計時器
      if (timer == null) {
        fn();
        timer = setTimeout(() => timer = null, time)
      }
    })
  }
})


//方案二
/**
 * 按鈕節流
 * 3秒内隻有第一次點選有效,防止重複送出資料。
 */
//注冊一個全局自定義指令 `v-throttle-disabled`
Vue.directive('throttle-disabled', {
	// 當被綁定的元素插入到 DOM 中時……
	inserted(el, binding) {
		let [event = "click", time = 2 * 1000] = binding.value
		el.addEventListener(event, () => {
			//預設監聽click事件
			//當 dom元素el 非禁用狀态時 将其設定為禁用狀态,同時設定計時器,規定時間後(預設2秒)啟用。
			if (!el.disabled) {
				el.disabled = true
				setTimeout(() => {
					el.disabled = false
				}, time)
			}
		})
	}
})
           

元件中使用

在.vue檔案中,data、methods同級的位置,添加如下配置:

,
directives: {
	debounce: {//自定義指令名,v-debounce
		// 指令的定義
    inserted: function(el, binding) {
      //binding.value,使用自定義指令v-throttle時填寫的參數
      //解構指派,定義了3個變量,将參數(數組)按順序進行指派
      let [fn, event = "click", time = 300] = binding.value
      let timer = null;
      el.addEventListener(event, () => {
        //預設監聽的事件為click
        //判斷計時器是否存在,不存在則執行函數fn,建立計時器
        if (timer == null) {
          fn();
          timer = setTimeout(() => timer = null, time)
        }
      })
    }
	}
},
           

全局引入

建立js檔案

在項目中建立 myDirective.js 檔案。通過export default暴露出來。

/*
 * @Author: qsdbl
 * @Date: 2022-02-10
 * @Description: 添加全局自定義指令。
 * 防抖,v-debounce。節流,v-throttle、v-throttle-disabled(可能無效)。
 * 示例:<el-button v-throttle="[resetData]">重新整理</el-button>,使用預設配置,監聽click事件,300毫秒内隻會執行一次函數resetData
 * 傳遞參數:<el-button v-throttle="[()=>resetData(param)]">重新整理</el-button>
 */
export default {
	install(Vue, Options) {
		/*
		 *  防抖,規定時間内(預設300毫秒)最後一次點選有效。
		 *  @param {?Number|300} time - 間隔時間,毫秒
		 *  @param {Function} fn - 執行函數
		 *  @param {?String|"click"} event - 事件類型 例:"click"
		 *  @param {Array} binding.value - [fn,event,time]
		 *  例:<el-button v-debounce="[resetData,`click`,300]">重新整理</el-button>
		 *  也可簡寫成:<el-button v-debounce="[resetData]">重新整理</el-button>
		 */
		// 注冊一個全局自定義指令 `v-debounce`
		Vue.directive('debounce', {
			// 當被綁定的元素插入到 DOM 中時……
			inserted: function(el, binding) {
				//binding.value,使用自定義指令v-debounce時填寫的參數
				//解構指派,定義了3個變量,将參數(數組)按順序進行指派
				let [fn, event = "click", time = 300] = binding.value
				let timer
				el.addEventListener(event, () => {
					//預設監聽的事件為click
					//判斷計時器是否存在,存在則清除計時器。重新建立計時器,到時間後執行函數fn
					if (timer) {
						clearTimeout(timer)
					}
					timer = setTimeout(() => fn(), time)
				})
			}
		})

		/*
		 *  節流,規定時間内可點選一次(第一次點選有效)。
		 *  @param {?Number|300} time - 間隔時間,毫秒
		 *  @param {Function} fn - 執行函數
		 *  @param {?String|"click"} event - 事件類型 例:"click"
		 *  @param {Array} binding.value - [fn,event,time]
		 *  例:<el-button v-throttle="[resetData,`click`,300]">重新整理</el-button>
		 *  傳遞參數則:<el-button v-throttle="[()=>resetData(param),`click`,300]">重新整理</el-button>
		 */
		// 注冊一個全局自定義指令 `v-throttle`
		Vue.directive('throttle', {
			// 當被綁定的元素插入到 DOM 中時……
			inserted: function(el, binding) {
				//binding.value,使用自定義指令v-throttle時填寫的參數
				//解構指派,定義了3個變量,将參數(數組)按順序進行指派
				let [fn, event = "click", time = 300] = binding.value
				let timer = null;
				el.addEventListener(event, () => {
					//預設監聽的事件為click
					//判斷計時器是否存在,不存在則執行函數fn,建立計時器
					if (timer == null) {
						fn();
						timer = setTimeout(() => timer = null, time)
					}
				})
			}
		})

		/*
		 *  節流方案二,通過禁用html标簽,規定時間内可點選一次(第一次點選有效)。
		 *  應用在封裝的元件中可能無效。
		 *  @param {?String|"click"} event - 事件類型 例:"click"
		 *  @param {?Number|2000} time - 間隔時間,毫秒
		 *  @param {Array} binding.value - [event,time]
		 *  例:<button v-throttle-disabled="[]">測試按鈕</button>
		 */
		//注冊一個全局自定義指令 `v-throttle-disabled`
		Vue.directive('throttle-disabled', {
			// 當被綁定的元素插入到 DOM 中時……
			inserted(el, binding) {
				let [event = "click", time = 2 * 1000] = binding.value
				el.addEventListener(event, () => {
					//預設監聽click事件
					//當 dom元素el 非禁用狀态時 将其設定為禁用狀态,同時設定計時器,規定時間後(預設2秒)啟用。
					if (!el.disabled) {
						el.disabled = true
						setTimeout(() => {
							el.disabled = false
						}, time)
					}
				})
			}
		})
	}
}
           

配置main.js檔案

在入口檔案main.js引入

//引入自定義指令,友善全局使用
import myDirective from '@/static/js/myDirective.js';
Vue.use(myDirective);
           

使用

這樣就可以全局使用myDirective.js裡面的自定義指令了,示例:

<button v-debounce="[debounceTest,`click`,3000]">測試按鈕-3秒</button>
<button v-debounce="[()=>debounceTest('hi')]">測試按鈕</button>
           
筆記學習自:51CTO-JackieDYH、vue 全局、局部引入

繼續閱讀