v-debounce实现

341 阅读1分钟

因为项目中很多按钮都需要做防抖处理 所以就学习了下v-directive的实现。废话不多说直接贴代码了

// utils/index.js
// 防抖函数 immediate: true  立即执行-前沿触发  false 为非立即触发-后沿触发 
export const debounce = (fn, delay = 1000, immediate = true) => {
    let timer = null
    return function() {
        if(timer) {
            clearTimeout(timer)
        }
        let now = immediate && !timer
        timer = setTimeout(()=>{    
            timer = null
            !immediate?  fn.call(this) : null
        }, delay)
        now ? fn.call(this) : null
    }
} 

然后创建directive文件夹存放 自定义指令

// directive/index.js
import Vue from "vue";
import { debounce } from '@/utils'

// 注:此为vue2.0+版本 vue3 生命周期钩子改变 beforeMount 
Vue.directive("debounce", {
  bind(el, binding) {
    let val = binding.value, // 获取指令传递的参数
        wait = 500 , // delay默认500
        immediate = false,
        type = 'click', 
        params = [],
        func
    if(val == null) return //如果没有传递任何参数则什么也不做
    if(typeof val !== 'object' && typeof val !== 'function') return //如何传递的参数既不是对象也不是函数则也什么都不做
    if(binding.arg) {
      wait = +binding.arg  // 获取冒号后的参数
    }
    if(binding.modifiers && binding.modifiers.immediate) {
      immediate = binding.modifiers.immediate
    }
    if(typeof val === 'function') func = val;//如果传递的是函数则直接赋给func
    // 如果是对象则对对象进行解析
    if(typeof val === 'object') { 
        func = val.func || function(){};
        type = val.type || 'click';
        params = val.params || [];			
    }
    el.$type = type;
    el.$handle = debounce(function(...args){
      return func.call(this, ...params.concat(args))
    }, wait, immediate)
    el.addEventListener(el.$type, el.$handle)
  },
  unbind(el) {
    el.removeEventListener(el.$type, el.$handle);
  }
});

使用方法


<template>
    <div class="vdirect">
        vue 自定义指令
        <!-- 需要传参类型  还有[]动态传参 有兴趣的小伙伴可以查看vue官方实现-->
        <button v-debounce:[wait].immediate="()=>demoFn(item)">防抖</button>
        <!-- 直接调用 -->
        <button v-debounce="demoFn">防抖</button>
    </div>
</template>
export default {
  name: 'App',
  data() {
    return {
      item: {
        key: 'hello',
      },
      wait: 3000
    }
  },
  methods: {
   demoFn(item) {
      console.log(item.key);  //  hello 传参版
    },
  }
}