vue 将防抖函数封装成自定义指令

  • Post author:
  • Post category:vue


指令即 v- 的形式,除了内置指令例如 v-model、v-show 以外,vue 允许注册

自定义

的指令。

自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。

  • 防抖: n 秒后再执行该事件,若在 n 秒内被重复触发,则重新计时
  • 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

1、在 src 文件夹下新建 utils 文件夹,用来存放公共方法或者 js 文件,utils 中新建一个 common.js 的文件,此处写防抖或节流函数。

/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true表示立即执行,false表示非立即执行
*/

export function debounce(func , wait , immediate = true){
  // 定义一个timeout计时器
  let timeout
  return function (){
    // 如果 timer 有值,代表有执行过定时器,就将定时器清除
    if(timeout) clearTimeout(timeout)
    // 默认立即执行方法,延后执行的话,会让人感觉有卡顿
    if(immediate){
      // 定义现在是否能执行
      let now = !timeout
      if(now) func.apply(this, arguments)
      // 不论timeout有没有值,都重新给timeout新添加一个定时器
      // 等待wait时间后,将timeout设为null,代表可以继续执行次function
      timeout = setTimeout(() => {
        timeout = null
      }, wait)
    }else{
      // 如果不是立即执行此函数,则在等待wait时间后执行方法
      timeout = setTimeout(()=>{
        func.apply(this, arguments)
      }, wait)
    }
  }
}

2、然后在src目录下新建一个 directives 目录,里面再创建一个 index.js,用来存放项目中的全局指令。

directives 下的 index.js 先引入 Vue 构造器和 debounce 函数,然后创建 Vue 的全局指令,在 bind 钩子函数中获取到 dom 元素el,并为其增加 click 事件监听器和经过 debounce 处理后的函数。

import Vue from 'vue'
import { debounce } from '@/utils/common'

// 定义一个名为 debounce 的指令
Vue.directive('debounce', {
  // 绑定的值为 el,和 binding
  // binding 的值为指令绑定的值,binding 中有哪些值,可以去 vue 官网中查看自定义指令
  bind(el, binding){
    let execFunc
    // 在函数传参与不传参调用的时候,打印出来的 binding.value 是不同的
    // v-debounce="getCount" 时,binding.value 是函数
    // v-debounce="getCount(index)" 时,binding.value 是 getCount(index) 的返回值,为 undefinded
    // 所以传参时调用需要包一层,如 v-debounce="[() => {getCount(index)}]",这样取 [binding.value][0] 即为所需函数
    console.log(binding.value)
    if(binding.value instanceof Array){
      // 函数传参
      const [func , time = 500] = binding.value
      execFunc = debounce(func, time)
    }else{
      // 函数不传参
      console.log('函数不传参')
      execFunc = debounce(binding.value, 500)
    }
    el.addEventListener('click', execFunc)
  }
})

3、 全局注册

在 main.js 主入口中,引入 directives 中的内容,即完成

全局

自定义指令的注册。

import '@/directives'

4、使用

注册完成后,即可在需要应用防抖的地方使用自定义指令。

需要注意的是,使用v-debounce=“getCount(param)”这种写法时,相当于将this.getCount(param)的函数执行结果返还给了binding.value,导致后面报错。所以如果应用防抖的函数里面需要传参,应该在函数外面再包裹一层,如包裹成数组或者对象。

示例:v-debounce=”[() => { getCount(4) }, 500]”

(1)传参使用方式(如果不这么写的话,会返回函数执行完之后的返回值。):

<el-button v-debounce="[$ev => { getCount($ev, 4)}, 500 ]">传参,且获取事件的测试</el-button>
<el-button v-debounce="[() => { getCount(4)}, 500 ]">传参,不获取事件的测试</el-button>

(2)不传参使用方式:

<el-button v-debounce="getCount">不传参测试</el-button>

参考:

自定义指令 | Vue.js



版权声明:本文为m0_59962820原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。