vue2.x通过指令实现v-debounce和v-throttle防抖节流的实现,亲测可用。

在vue2.x中,防抖和节流一般是通过引入防抖函数debounce和节流函数throtte,对事件回调进行一层包裹,然后在模板中绑定包裹后的事件回调,这样每个需要用的地方都需要进行防抖,节流函数的导入,事件回调的包裹,比较麻烦。通过摸索,有以下两种方法。

重写Vue.protyoep.$on方法

通过重写Vue.prototype.$on方法,统一对xx事件进行防抖和节流,(没试过,应该可行)

在这里插入图片描述
伪代码如下:

const oldOn = Vue.prototype.$on
Vue.prototype.$on = function(...args){
	const event = args[0]
	let fn = args[1]
	if(某某条件){
		fn = debounce(fn)
		// fn = throttle(fn)
	}
	oldOn.call(this,fn)
}

通过指令包裹vnode的存放回调

使用方法,只需要在组件或者dom元素上对需要防抖或者节流的事件添加以下指令即可
v-debounce:事件.毫秒数

<input @click="fn" v-debounce:click.300 v-debounce:change.300 />

实现细节

/**
 * 防抖函数
 * @param {*} fn
 * @param {*} wait 防抖间隔
 * @param {*} immediate 立即执行
 * @returns
 */
function debounce(fn, wait = 300, immediate = true) {
  let t = null
  let canChangeImmdiate = !!immediate
  if (typeof fn !== "function") {
    throw new TypeError("debounce 第一个参数必须是函数")
  }

  return function debounceFn(...args) {
    t && clearTimeout(t)
    if (immediate) {
      if (!t) {
        fn.apply(this, args)
        immediate = false
      }
    } else {
      t = setTimeout(() => {
        fn.apply(this, args)
        if (canChangeImmdiate) {
          immediate = true
          t = null
        }
      }, wait)
    }
  }
}

// 直接添加在组件或者元素上 v-debounce:click.300 v-debounce:change.300 300ms
// vue2.6.x在update中,vue2.7.x在insertd钩子中起作用
Vue.directive("debounce", {
  update(el, bind, vnode) {
    // 默认给click事件添加防抖
    const { value: fn, arg = "click", modifiers } = bind
    const { immediate = false } = modifiers
    const modNumKeys = Object.keys(modifiers).filter((key) => !isNaN(+key))
    const wait = modNumKeys.length > 0 ? modNumKeys[0] : 300

    if (vnode.componentInstance) {
      // 组件
      for (const [evtName, handlers] of Object.entries(vnode.componentInstance._events)) {
        if (arg == evtName) {
          vnode.componentInstance._events[evtName] = handlers.map((handler) =>
            debounce(handler, wait, immediate)
          )
        }
      }
    } else {
      // dom元素
      for (const [evtName, handler] of Object.entries(vnode.data.on)) {
        if (evtName == arg) {
          if (Array.isArray(vnode.data.on[arg].fns)) {
            vnode.data.on[arg].fns = vnode.data.on[arg].fns.map((fn) =>
              debounce(fn, wait, immediate)
            )
          } else {
            console.log(wait, immediate)
            vnode.data.on[arg].fns = debounce(vnode.data.on[arg].fns, wait, immediate)
          }
        }
      }
    }
  }
})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue2中实现防抖节流可以使用Vue指令和方法来实现。 ## 防抖 防抖实现方法是在一定时间内只执行一次方法,如果在这段时间内又有触发事件的操作,那么计时器就会被重新计时,直到时间结束才会执行方法。 ### 指令实现Vue2中可以使用v-debounce指令实现防抖: ```html <template> <button v-debounce:click="handleClick">Click me</button> </template> <script> export default { methods: { handleClick() { console.log('Clicked'); } } } </script> ``` 可以看到v-debounce指令绑定在click事件上,这样就会在点击按钮时执行handleClick方法,但是在执行handleClick方法之前会先执行防抖函数。 下面是v-debounce指令实现: ```javascript Vue.directive('debounce', { inserted: function (el, binding) { let timer; el.addEventListener('click', () => { if (timer) clearTimeout(timer); timer = setTimeout(() => { binding.value(); }, 500) }) } }) ``` 上面的代码实现了一个叫做debounce的指令,它会在元素插入到DOM中时绑定一个click事件,在click事件中执行防抖函数,最后执行传入的回调函数。 ### 方法实现 除了指令,我们也可以在Vue2的方法中实现防抖。 ```html <template> <button @click="debounceClick">Click me</button> </template> <script> export default { methods: { debounce(fn, delay) { let timer; return function () { if (timer) clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, arguments); }, delay) } }, handleClick() { console.log('Clicked'); }, debounceClick: debounce(this.handleClick, 500) } } </script> ``` 上面的代码中我们在Vue2的methods中实现了一个debounce方法,它返回一个函数,这个函数会在delay时间内执行一次fn方法。我们在handleClick方法前面加上了debounce,这样每次点击按钮时就会执行debounceClick方法,而不是直接执行handleClick方法。 ## 节流 节流实现方法是在一段时间内只执行一次方法,如果在这段时间内有多次触发事件的操作,那么只有第一次触发事件的操作会执行方法,其余的操作会被忽略,直到时间结束才会重新计时。 ### 指令实现Vue2中可以使用v-throttle指令实现节流: ```html <template> <button v-throttle:click="handleClick">Click me</button> </template> <script> export default { methods: { handleClick() { console.log('Clicked'); } } } </script> ``` 可以看到v-throttle指令绑定在click事件上,这样就会在点击按钮时执行handleClick方法,但是在执行handleClick方法之前会先执行节流函数。 下面是v-throttle指令实现: ```javascript Vue.directive('throttle', { inserted: function (el, binding) { let timer; el.addEventListener('click', () => { if (!timer) { timer = setTimeout(() => { timer = null; binding.value(); }, 500) } }) } }) ``` 上面的代码实现了一个叫做throttle指令,它会在元素插入到DOM中时绑定一个click事件,在click事件中执行节流函数,最后执行传入的回调函数。 ### 方法实现 除了指令,我们也可以在Vue2的方法中实现节流。 ```html <template> <button @click="throttleClick">Click me</button> </template> <script> export default { methods: { throttle(fn, delay) { let timer; return function () { if (!timer) { timer = setTimeout(() => { timer = null; fn.apply(this, arguments); }, delay) } } }, handleClick() { console.log('Clicked'); }, throttleClick: throttle(this.handleClick, 500) } } </script> ``` 上面的代码中我们在Vue2的methods中实现了一个throttle方法,它返回一个函数,这个函数会在delay时间内执行一次fn方法。我们在handleClick方法前面加上了throttle,这样每次点击按钮时就会执行throttleClick方法,而不是直接执行handleClick方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值