【Vue3 Hook】实现 useTimeout 代替 setTimeout

847 阅读2分钟

前言

大家好,我是vue-hooks-plus的作者,vue-hooks-plus 是一个高质量简约优雅的 vue3 hook 库,通过这个库在这里和大家分享如何通过 vue3的组合式API 高质量的封装出业务中常用的 hook 函数。

Why?

  • 控制是否立即执行
  • 组件卸载时清除定时器
  • 动态控制延迟

useTimeout

思路

  • 确定好参数的结构,参数依次为 fndelayoptions
  • fn是函数
  • delay 可以是空也可以是一个响应式的值或者一个纯数字
  • options携带 immediate 判断是否立即执行

先贴源码

import { watchEffect, Ref, unref } from 'vue'

function useTimeout(
  fn: () => void,
  delay?: Ref<number | undefined> | number,
  options?: {
    immediate?: boolean
  },
) {
  const immediate = options?.immediate
  if (immediate) {
    fn()
  }

  watchEffect(onInvalidate => {
    if (isRef(delay)) {
      if (typeof delay.value !== 'number' || delay.value < 0) return
    } else {
      if (typeof delay !== 'number' || delay < 0) return
    }
    const _deply = unref(delay)
    const timer = setTimeout(() => {
      fn()
    }, _deply)
    onInvalidate(() => {
      clearInterval(timer)
    })
  })
}

export default useTimeout

一、先判断 immediate 执行


const immediate = options?.immediate

实现了控制是否立即执行

二、利用 watchEffect 的机制

如果传入的是一个 ref 那么这个依赖会被自动收集并且执行,实现了动态控制延迟。

通过 isRefunref 很好的处理响应式和非响应式的关系,代码简洁优雅

三、巧妙的通过 watchEffect 的机制清除副作用

在组件卸载或者依赖变化的时候会清除副作用

 onInvalidate(() => {
      clearInterval(timer)
    })  

可以从上看出,即使是一个简单的 hook,想让它变优雅高效,会有很多点需要注意。

用法

const valueRef = ref(0)

useTimeout(
    () => {
      valueRef.value += 1
    },
    2000,
    {
      immediate: true,
    },
  )

Params

参数说明类型
fn待执行函数() => void
delay定时时间(单位为毫秒),支持动态变化,,当取值为 undefined 时会停止计时器Ref<number | undefined >|number | undefined
immediate是否立即执行boolean

Result

参数说明类型
clearTimeout清除定时器() => void

自我宣传

喜欢的小伙伴可以关注(star 🌟)一下作者的库。

GitHub 活跃高,想和作者一起共建的欢迎大家提 Issue 和 PR