ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Airi 项目中的 VueUse useTimeout 实战指南:响应式延时、可控定时与源码级原理

Airi 项目中的 VueUse useTimeout 实战指南:响应式延时、可控定时与源码级原理 Airi 项目中的 VueUse useTimeout 实战指南响应式延时、可控定时与源码级原理【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airiuseTimeout 是 VueUse 中位于 Animation动画分类下的响应式组合式函数它把延时后置为true这个需求抽象成一个可响应、可控制、可复用的定时器。本文以 .agents/skills/vueuse-functions/references/useTimeout.md 为核心骨架结合 Airi 仓库中stage-tamagotchi桌面端与stage-ui的实际调用代码讲解 useTimeout 的完整 API、与useTimeoutFn的差异以及它在真实项目中的落地姿势。读完本文你将掌握如何用 useTimeout 写出延时后自动变为 true 的响应式状态如何通过controls暴露start / stop / isPending手动控制定时器如何传入响应式时长与完成回调以及底层Stoppable接口如何保证组件卸载时自动清理定时器、避免内存泄漏。一、useTimeout 是什么把 setTimeout 变成响应式状态VueUse 中的useTimeout是一个响应式布尔值它在经过指定时间后从false变为true。它与原生setTimeout的核心区别在于原生setTimeout是一次性、命令式的回调调用状态变化无法被模板或watch直接感知useTimeout返回的是ComputedRefboolean可以像任何 Vue 响应式状态一样用于模板渲染、watch、computed派生甚至参与动画过渡。在 SKILL.md 的函数清单中useTimeout 被归入 Animation 分类描述为 Reactive value that becomestrueafter a given time其调用规则Invocation为AUTO即只要适用就应优先使用 VueUse 组合式函数而非手写自定义代码以提升可读性、可维护性与性能。最简用法import { useTimeout } from vueuse/core const ready useTimeout(1000)1 秒之后ready.value变为true。默认情况下定时器立即启动immediate: true所以你甚至不需要手动调用任何函数只需在模板或逻辑里读取readyscript setup langts import { useTimeout } from vueuse/core const ready useTimeout(1000) /script template p{{ ready ? 已就绪 : 等待中… }}/p /template二、开启 controlsstart / stop / isPending 手动控制很多场景下我们需要的不是一个静默的倒计时而是一个可暂停、可重启的定时器。传入{ controls: true }后useTimeout 会额外返回start、stop、isPending三个控制项import { useTimeout } from vueuse/core const { ready, start, stop, isPending } useTimeout(1000, { controls: true }) // 检查定时器是否仍在计时 console.log(isPending.value) // true // 停止定时器ready 将停留在 false stop() // 重新开始/重启定时器 start()注意区分返回值类型含义readyComputedRefboolean到点后变为true的响应式状态start() void启动或重新启动定时器非响应式版本见下节stop() void停止定时器isPendingComputedRefboolean定时器是否仍在计时中这组返回值的类型签名对应Stoppable接口——VueUse 中凡是实现Stoppable的组合式函数都承诺在组件卸载时自动调用stop()完成清理这正是用它替换手写setTimeout不会产生内存泄漏的底层保证。三、Options 参数一览useTimeout的第二个参数是UseTimeoutOptions它继承自UseTimeoutFnOptions并追加了两个字段OptionTypeDefaultDescriptioncontrolsbooleanfalse是否暴露start、stop、isPending控制项immediatebooleantrue是否立即启动定时器callback() void—定时器完成时触发的回调三个选项的相互作用controls只影响返回值形状为false时返回单个ComputedRefboolean为true时返回{ ready, start, stop, isPending }的组合对象下文的类型声明会给出精确签名。immediate: false配合controls: true是手动门闩模式定时器不会自动启动只有显式调用start()才开始计时。这在用户触发后才开始等待的交互中非常有用。callback与ready并不冲突到点时两者都会触发/置位你可以用ready驱动 UI用callback执行副作用比如发出埋点、切换路由、释放资源。四、Callback到点后的副作用钩子import { useTimeout } from vueuse/core useTimeout(1000, { callback: () { console.log(Timeout completed!) }, })callback的类型是() void也就是UseTimeoutOptions中callback?: Fn所指的通用函数类型。它是轻量的完成通知钩子适合在倒计时结束瞬间执行一段与 UI 状态解耦的逻辑。五、响应式时长interval 可以是 ref 或 getteruseTimeout 的时长参数类型是MaybeRefOrGetternumber这意味着你不仅可以传字面量还可以传ref或 getter 函数让时长本身具备响应性import { useTimeout } from vueuse/core const duration ref(1000) const ready useTimeout(duration) // 修改时长在启用 controls 时只影响未来启动的定时器 duration.value 2000注意原文档明确提示的行为细节修改时长只影响未来的定时器。如果定时器已经在计时中中途修改duration不会打断当前这一次计时如果你需要以新时长重新开始正确做法是更新 ref 后显式调用start()重启。这也解释了为什么响应式时长通常与controls: true搭配使用才最有价值——单纯的ready布尔值拿到的是旧时长下的一次性结果。六、Type Declarations 精读重载签名与兼容别名原文档给出了完整类型声明这里逐段拆解其含义export interface UseTimeoutOptions Controls extends boolean, extends UseTimeoutFnOptions { /** * Expose more controls * * default false */ controls?: Controls /** * Callback on timeout */ callback?: Fn }UseTimeoutOptions通过泛型Controls把controls的取值直接映射到返回类型上从而实现传了controls: true就自动得到完整控制对象的编译期类型推断。export type UseTimeoutReturn | ComputedRefboolean | ({ readonly ready: ComputedRefboolean } Stoppable)UseTimeoutReturn是联合类型要么是纯ComputedRefboolean要么是readyStoppable的组合。Stoppable正是提供start/stop/isPending的来源。/** * deprecated use UseTimeoutReturn instead */ export type UseTimoutReturn UseTimeoutReturn注意一个历史遗留UseTimoutReturn少写了一个字母o是官方标记deprecated的旧别名类型上与UseTimeoutReturn完全等价。如果你是 VueUse 早期版本的迁移用户看到这个别名不必困惑新代码应统一使用UseTimeoutReturn。两个重载的函数签名export declare function useTimeout( interval?: MaybeRefOrGetternumber, options?: UseTimeoutOptionsfalse, ): ComputedRefboolean export declare function useTimeout( interval: MaybeRefOrGetternumber, options: UseTimeoutOptionstrue, ): { ready: ComputedRefboolean } Stoppable从重载可以看出第一个签名中interval是可选的省略时默认0立即置true第二个签名要求interval必填且controls: true。这一设计让无参场景默认返回一个会立刻/按时变为 true 的 ref和可控场景需要 interval在类型上被严格区分。七、源码级原理useTimeout 与 useTimeoutFn 的分工useTimeout 本质上是useTimeoutFnuseTimeoutFn.md之上的一个状态化封装。看useTimeoutFn的声明就能理解两者关系export declare function useTimeoutFnCallbackFn extends AnyFn( cb: CallbackFn, interval: MaybeRefOrGetternumber, options?: UseTimeoutFnOptions, ): UseTimeoutFnReturnCallbackFn其中UseTimeoutFnOptions提供OptionTypeDefaultDescriptionimmediatebooleantrue是否立即启动定时器immediateCallbackbooleanfalse调用start()时是否立即执行回调对比两条使用路径useTimeoutFn(cb, interval)核心职责是到点执行回调返回isPending/start/stop不维护布尔状态useTimeout(interval, { callback })在内部用useTimeoutFn把到点翻译成ready true的响应式状态callback则是透传给你的副作用。因此如果你的目标是等待一段时间后执行一段代码useTimeoutFn更直接如果目标是让某个布尔状态在延时后翻转并参与渲染/watchuseTimeout是更贴合语义的选择。本文聚焦的 useTimeout 属于前者之上的状态化抽象。Airi 中的真实对照controls 模式的完整范本Airi 的桌面端舞台stage-tamagotchi在控制岛Controls Island角落搬迁动画中用三个useTimeoutFn同样基于Stoppable控制模型串联了离开旧角落 → 准备入场 → 抵达新角落的阶段机controls-island-root.vueconst { start: finishArrival, stop: stopArrival } useTimeoutFn(() { motionPhase.value idle relocationTarget.value undefined }, placementArrivalDurationMs, { immediate: false }) const { start: startArrival, stop: stopEnterPreparation } useTimeoutFn(() { motionPhase.value arriving finishArrival() }, placementEnterPreparationMs, { immediate: false }) const { start: finishLeave, stop: stopLeave } useTimeoutFn(() { if (!relocationTarget.value) { motionPhase.value idle return } dock.value relocationTarget.value motionPhase.value entering startArrival() }, placementLeaveDurationMs, { immediate: false })这段代码把immediate: false、start()、stop()用到了极致三个定时器都不自动启动由relocate()在用户拖动窗口触发搬迁时先stopRelocation()取消所有未完成任务再按阶段逐个start()接力。这正是文档中immediate: false配合controls实现手动门闩的真实写照。Airi 中的响应式时长范本OIDC Token 定时刷新stage-ui 的认证 Store 用useTimeoutFn实现了 OIDC access token 的寿命 80% 时刻刷新调度完美示范了响应式 ref 作为时长参数的用法const refreshDelayMs ref(0) const { start: startRefreshTimer, stop: stopRefreshTimer } useTimeoutFn( () { void useAuthStore().refreshTokenNow() }, refreshDelayMs, { immediate: false }, ) function scheduleTokenRefresh(expiresInSeconds: number): void { stopRefreshTimer() // Guard against missing/invalid lifetimes例如 token 响应缺少 expires_in。 // useTimeoutFn 在 NaN/0 延时下会立即触发并造成刷新死循环——这里直接跳过调度。 if (!Number.isFinite(expiresInSeconds) || expiresInSeconds 0) return // 在生命周期 80% 的时间点刷新 refreshDelayMs.value expiresInSeconds * 0.8 * 1000 startRefreshTimer() }三个要点值得对照前文吸收immediate: falsestart()定时器只在scheduleTokenRefresh里手动启动避免 Store 初始化时误触发刷新响应式时长refreshDelayMs是ref(0)每次刷新成功后按新的expires_in更新再start()同一套代码复用于不同寿命的 token边缘守卫注释里明确提到 useTimeoutFn with NaN/0 delay would fire immediately即非有限/非正时长会立刻触发回调——这与前文interval 省略时默认 0的类型语义呼应提醒开发者对动态时长必须做有效性校验。这个案例也直接印证了 SKILL.md 的核心主张优先用 VueUse 组合式函数而非手写setTimeout——useTimeoutFn在组件/Store 销毁时自动清理定时器代码里不需要再手动clearTimeout。八、与相邻定时类函数的选型对比在 VueUse 中与 useTimeout 相邻的定时/动画函数还有useInterval、useIntervalFn、useRafFn它们同属 Animation 分类见 SKILL.md 中 Animation 一节函数语义典型场景useTimeout延时后布尔值翻转为true一次性等待、就绪门闩、延时展示useTimeoutFn延时后执行回调Stoppable一次性副作用、节流式调度useInterval每隔 N 毫秒递增的响应式计数器倒计时、轮询进度展示useIntervalFnsetInterval的可控包装周期性任务useRafFn每帧调用一次回调动画循环、渲染节流Airi 中也能找到后者在用的实例例如 use-chat-history-top-fade.ts 用useRafFn把滚动到底部后淡出顶部历史的更新推迟到下一帧避免布局抖动use-virtualizer-scroll.ts 也用useRafFn做滚动渲染节流。选择依据很简单一次性延时看 useTimeout/useTimeoutFn周期性任务看 useInterval/useIntervalFn逐帧动画看 useRafFn。九、实战要点与陷阱清单综合原文档、类型声明与仓库证据这里给出 useTimeout 的实战 checklist默认自动启动immediate默认为true只想要到点翻 true就一行搞定需要手动触发则必须controls: trueimmediate: false。controls 三件套start()可重启计时stop()立即中止isPending可读是否在计时它们来自Stoppable接口组件卸载时自动清理。响应式时长只影响未来定时器中途改 interval 不会打断当前计时需要新时长生效就改 ref 后重新start()。动态时长要防非法值参考 auth.ts 的做法对来自外部token 响应、接口数据的时长先做Number.isFinite与 0校验避免 NaN/负值导致定时器立即触发。callback 与 ready 分工UI 用ready驱动副作用放callback保持状态与行为的解耦。与 useTimeoutFn 的选择需要的是状态选 useTimeout需要的是到点执行函数选 useTimeoutFn两者共享Stoppable控制模型可互相替代实现。旧别名注意UseTimoutReturn已废弃新代码一律写UseTimeoutReturn。十、延伸阅读函数索引与调用规则.agents/skills/vueuse-functions/SKILL.md本文主文档含完整类型声明useTimeout.md底层实现对照useTimeoutFn.md仓库实战控制岛动画阶段机 controls-island-root.vue、OIDC 定时刷新 auth.ts【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表