vuejs-challenges icon indicating copy to clipboard operation
vuejs-challenges copied to clipboard

20 - 节流点击指令

Open kalu5 opened this issue 2 years ago • 0 comments

// 你的答案
<script setup lang='ts'>
import { DirectiveBinding } from 'vue'

/**
 * Implement the custom directive
 * Make sure the `onClick` method only gets triggered once when clicked many times quickly
 * And you also need to support the debounce delay time option. e.g `v-debounce-click:ms`
 *
*/
interface Callback {
  (): void
}
  
function Debounce<T extends Callback>(fn: T, delay: number, immediate: boolean ): T {
  let timer = null
  return function () {
     const context = this,
           args = arguments;
     if (timer) clearTimeout(timer);
     if (immediate) {
       const execute = !timer;
       setTimeout(() => {
         timer = null;
       }, delay);
       if (execute) fn.apply(context, args)
     } else {
       timer = setTimeout(() => {
          fn.apply(context, args)
        }, delay)
     }  
  }
}

const VDebounceClick = {
  mounted(el: HTMLButtonElement, binding: DirectiveBinding) {
    const { arg, value } = binding
    el.addEventListener('click', Debounce(value, arg), false)
  }
}

function onClick() {
  console.log("Only triggered once when clicked many times quickly")
}

</script>

<template>
  <button v-debounce-click:2000="onClick">
    Click on it many times quickly
  </button>
</template>

kalu5 avatar Sep 15 '22 10:09 kalu5