vue 中使用防抖函數組件

初級

1、先寫好防抖函數

/**
 * @desc 防抖函數
 * @param {需要防抖的函數} func
 * @param {延遲時間} wait
 * @param {是否立即執行} immediate
 */
export function debounce(func, wait, immediate) {
  let timeout
  
  return function(...args) {
    let context = this
    if (timeout) clearTimeout(timeout)

    if (immediate) {
      let callNow = !timeout
      timeout = setTimeout(function() {
        timeout = null
      }, wait)
      if (callNow) func.apply(context, args)
    } else {
      timeout = setTimeout(function() {
        func.apply(context, args)
      }, wait)
    }
  }
}

2、然後在要使用的組件裏 import 進來

import { debounce } from 'xxx'

export default {
	data: {
		return {
			vm: this
		}
	},
	methods: {
		toDoSth: debounce((vm) => {
			// 這裏將當前組件實例當參數傳入
			// 就可以使用實例中定義的一些屬性、方法
			// 補充一下,這裏如果換成非箭頭函數的寫法,也可以直接訪問實例。
		}, 
		500, 
		true
		)
	}
}

3、在組件方法中使用

template:

<div @click="toDoSth(vm)"></div>

高級

雖然上面的寫法已經能解決問題了,但是總覺得不夠美觀。
在網上搜索一番,看到有個哥們將防抖封裝成一個組件,果然和我想的一樣。不過這哥們直接將上下文當參數傳進來了,比我把整個實例傳進來高明,我在這個基礎上添加了 immediate 的功能,還有添加了默認不傳 event 參數的情況處理。

debounce.js 文件:

import Vue from 'vue'

const debounce = (func, time, ctx, immediate) => {
  let timer
  const rtn = (...params) => {
    clearTimeout(timer)

    if (immediate) {
      let callNow = !timer
      timer = setTimeout(() => {
        timer = null
      }, time)
      if (callNow) func.apply(ctx, params)
    } else {
      timer = setTimeout(() => {
        func.apply(ctx, params)
      }, time)
    }
  }
  return rtn
}

Vue.component('Debounce', {
  abstract: true,
  props: ['time', 'events', 'immediate'],
  created() {
    this.eventKeys = this.events && this.events.split(',')
  },
  render() {
    const vnode = this.$slots.default[0]
  
    // 如果默認沒有傳 events,則對所有綁定事件加上防抖
    if (!this.eventKeys) {
      this.eventKeys = Object.keys(vnode.data.on)
    }
    
    this.eventKeys.forEach(key => {
      vnode.data.on[key] = debounce(
        vnode.data.on[key],
        this.time,
        vnode,
        this.immediate
      )
    })

    return vnode
  }
})

使用方式:

1、引入 debounce.js 文件

import 'xxx/debounce.js'

export default {
	methods: {
		toDoSth(e) {
			// 這裏正常寫就可以了
		}
	}
}

2、在模版裏使用。
其中time爲必選參數。 event 和 immediate 參數都是可選參數。
如果組件下有多個事件綁定,那麼 event 可以自定義需要進行防抖處理的事件。
如果需要立即執行的話,可以將 immediate 參數設置爲 true。

<Debounce :time="500" event="click" :immediate="true">
  <button @click="toDoSth($event, 1)">click me</button>
</Debounce>

到此就完成了一次 Debounce 組件的封裝。

參考:

最後附上這位哥們的原帖:
https://juejin.im/post/5c2dc7a9e51d4573c8491e77

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章