当前位置: 代码网 > it编程>编程语言>Javascript > 使用Vue封装一个可随时暂停启动无需担心副作用的定时器

使用Vue封装一个可随时暂停启动无需担心副作用的定时器

2024年11月25日 Javascript 我要评论
现成轮子:vueuse 库的 useintervalfn 方法是什么?创建定时器的组合式函数为什么要用它?定时执行回调(入参;回调函数、时间间隔、配置项)控制定时器的行为(返回:开始、暂停定时器的方法

现成轮子:vueuse 库的 useintervalfn 方法

是什么?

创建定时器的组合式函数

为什么要用它?

定时执行回调(入参;回调函数、时间间隔、配置项)

控制定时器的行为(返回:开始、暂停定时器的方法)

响应式间隔(入参的时间间隔可以是一个 响应式引用ref 或者一个函数,当它的值改变,定时器会自动更新其间隔时间,无需手动重启定时器)

立即执行选项(入参 options.immediate 控制 是否在初始化时立即启动定时器;入参 options.immediatecallback 控制是否在调用resume方法猴立即执行一次回调函数)

怎么用?

官网有说怎么安装依赖,就不过多解释:https://vueuse.org/shared/useintervalfn/

分析源码 & 自己手写一个

源码

https://github1s.com/vueuse/vueuse/blob/main/packages/shared/useintervalfn/index.ts

自己手写

安装vue-demi依赖后,就可以开始手写啦~

import type { computedref, ref, shallowref, writablecomputedref } from 'vue-demi'
import { getcurrentscope, isref, onscopedispose, ref, unref, watch } from 'vue-demi'

/**
 * void函数
 */
export type fn = () => void

/**
 * 任意函数
 */
export type anyfn = (...args: any[]) => any

/**
 * 它可能是一个 ref 对象,或者一个普通的值
 */
export type mayberef<t = any> =
| t
| ref<t>
| shallowref<t>
| writablecomputedref<t>

/**
 * 它可能是一个 ref 对象,或者一个普通的值,或者一个 getter 函数
 * @param cb 
 * @param interval 
 */
export type maybereforgetter<t = any> = mayberef<t> | computedref<t> | (() => t)

/**
 * 获取值、ref 或 getter 的实际值
 */
export function tovalue<t>(r: maybereforgetter<t>): t {
  return typeof r === 'function' ? (r as anyfn)() : unref(r)
}

/***
 * 是否为客户端
 */
export const isclient = typeof window !== 'undefined' && typeof document !== 'undefined'

/**
 * 是否处于一个 vue 3 的响应式 effect 生命周期的作用域内。如果是的话,它会注册一个清理函数(fn 参数),该函数会在作用域结束时执行;如果不是在这样的作用域内,那么它将不做任何操作。
 * @param fn 
 */
export function tryonscopedispose(fn: fn) {
  if (getcurrentscope()) {
    onscopedispose(fn)
    return true
  }
  return false
}


export interface useintervaloptions {
  /**
   * 立即执行这个定时器
   */
  immediate?: boolean
  /**
   * 在调用 resume 函数后,立即执行回调函数
   */
  immediatecallback?: boolean
}

export interface pausable {
  /**
   * 一个 ref 表示 pausable 实例是否处于活动状态
   */
  isactive: readonly<ref<boolean>>
  /**
   * 暂停定时器
   */
  pause: fn
  /**
   * 恢复定时器
   */
  resume: fn
}

export function useintervalfn(cb: fn, interval: maybereforgetter<number> = 1000, options: useintervaloptions = {}): pausable {
  const {
    immediate = true,
    immediatecallback = true
  } = options

  let timer: returntype<typeof setinterval> | null = null
  const isactive = ref(false)

  function clean() {
    if (timer) {
      clearinterval(timer)
      timer = null
    }
  }

  function pause() {
    isactive.value = false
    clean()
  }

  function resume() {
    const intervalvalue = tovalue(interval)
    if (intervalvalue <= 0) {
      return
    }
    isactive.value = true

    if (immediatecallback){
      cb()
    }

    clean()

    if (isactive.value) {
      timer = setinterval(cb, intervalvalue)
    }
  }

  
  if (immediate && isclient) {
    resume()
  }

  if (isref(interval) || typeof interval === 'function') {
    const stopwatch = watch(interval, () => {
      if (isactive.value && isclient) {
        resume()
      }
    })
    tryonscopedispose(stopwatch)
  }

  tryonscopedispose(pause)

  return {
    isactive,
    pause,
    resume
  }
}

到此这篇关于使用vue封装一个可随时暂停启动无需担心副作用的定时器的文章就介绍到这了,更多相关vue封装定时器内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com