新闻详情

新闻详情

首页 / 资讯中心 / 详情

掌握 VueUse `useToggle`:在 airi 项目中编写优雅的布尔状态切换逻辑

发布时间:2026/9/10 12:18:45来源:尧图网络
掌握 VueUse `useToggle`:在 airi 项目中编写优雅的布尔状态切换逻辑
掌握 VueUseuseToggle在 airi 项目中编写优雅的布尔状态切换逻辑【免费下载链接】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导读useToggle是 VueUse 中最常用的工具函数之一它把「布尔值切换」这一高频操作封装为一个简洁、类型安全且支持自定义真/假值的组合式函数。本文将结合 airi 仓库中 useToggle 参考文档 与 use-theme.ts 等真实源码实现完整讲解其两种调用形态、自定义值、事件绑定陷阱与类型声明帮助你写出更简洁、可维护的 Vue 状态切换代码。一、为什么需要useToggle从「重复样板代码」到「一行切换」在 Vue 应用中开关类状态如侧边栏展开、弹窗显示、深色模式无处不在。手写版本往往长这样const visible ref(false) function toggleVisible() { visible.value !visible.value } function setVisible(value: boolean) { visible.value value }而useToggle将上述逻辑压缩为一次调用import { useToggle } from vueuse/core const [value, toggle] useToggle()这一设计思路与 airi 仓库.agents/skills/vueuse-functions/SKILL.md中声明的技能宗旨完全一致优先使用 VueUse 组合式函数而非自造代码以提升可读性、可维护性与性能。在 SKILL.md 的功能表中useToggle被归类在 Utilities 分类下描述为 “A boolean switcher with utility functions”调用规则为AUTO——即在合适的场景下应自动使用。二、两种调用形态解构元组 与 接收 refuseToggle的重载设计让它可以同时服务「全新状态」与「既有状态」两种场景。形态一不传参数返回[value, toggle]元组import { useToggle } from vueuse/core const [value, toggle] useToggle()此时value是一个ShallowRefbooleantoggle是一个切换函数。两者通过数组解构返回这与 Vue 3 中v-model常见写法一样直观。形态二传入 ref返回纯切换函数当你已经有一个 ref例如由useDark生成的isDarkuseToggle会直接接管这个 ref 并只返回一个切换函数不再重复创建状态import { useDark, useToggle } from vueuse/core const isDark useDark() const toggleDark useToggle(isDark)这是 airi 项目中实际采用的模式。在 packages/ui/src/composables/use-theme.ts 中主题模块正是这样把「状态」与「切换动作」绑定在一起import { useDark, useToggle } from vueuse/core import { LocalStorageShim } from ../utils const isDark useDark({ disableTransition: true, // NOTICE: for histoire, used in packages/stage-ui, localStorage global variable exists but storage.getItem is not a function wil // thrown, here we added LocalStorageShim to avoid this issue, and it will fallback to real localStorage when its available. storage: localStorage in globalThis localStorage ! null getItem in localStorage typeof localStorage.getItem function ? localStorage : new LocalStorageShim(), }) const toggleDark useToggle(isDark) export function useTheme() { return { isDark, toggleDark, } }注意这里的两个细节传入 ref 时返回的是函数而非元组因此useTheme()解构出的是{ isDark, toggleDark }toggleDark直接可用作事件处理器useToggle不会创建新的状态它读写的就是传入的isDark保证了「读取状态」与「切换状态」指向同一个响应式源。两种形态的判别方式useToggle通过第一个参数的类型来区分行为参数是一个RefT返回(value?: T) T即仅一个切换函数参数缺失或为普通值返回[ShallowRefT, (value?: T) T]元组。这与 VueUse 许多函数的「ref 优先」设计一脉相承也是该技能文档建议「先检查 VueUse 是否已有现成函数」的原因。三、切换函数的三类调用方式无论哪种形态返回的切换函数都支持三种调用方式const [value, toggle] useToggle() toggle() // 在 true 与 false 之间切换 toggle(true) // 强制设置为指定值 toggle(false) // 强制关闭 // 切换函数会返回切换后的新值便于链式使用 const newValue toggle() // 返回切换后的最新值返回值的新值语义toggle()在翻转后会返回新值这意味着可以直接把它接进其它逻辑例如同步到日志、发送到服务端或作为其它函数入参const [muted, toggleMuted] useToggle() // 每次切换后立刻拿到最新状态 watchEffect(() console.log(muted , muted.value)) const latest toggleMuted() // latest 与 muted.value 一致这一「返回值 新值」的约定让useToggle比手写value.value !value.value更具表达力你既能拿它当赋值器又能拿它当读取器。四、自定义真值与假值不止于 true / falseuseToggle并不局限于布尔类型。通过UseToggleOptions中的truthyValue与falsyValue可以让状态在两个自定义值之间切换例如字符串枚举import { useToggle } from vueuse/core const [value, toggle] useToggle(on, { truthyValue: on, falsyValue: off, }) toggle() // off toggle() // on这在需要把 UI 状态直接映射为接口参数如open/closed、enabled/disabled时非常有用省去了额外的映射层。自定义值也可以是响应式的truthyValue与falsyValue的类型是MaybeRefOrGetter意味着你可以传入 ref 或 getter让「目标真值/假值」本身动态变化import { useToggle } from vueuse/core import { ref } from vue const truthy ref(yes) const falsy ref(no) const [value, toggle] useToggle(yes, { truthyValue: truthy, falsyValue: falsy, })此时如果外部将truthy.value改为是则value的判等逻辑会跟随新的目标值。泛型推导从类型声明可以看出Truthy与Falsy是两个独立泛型最终值类型T Truthy | Falsyexport interface UseToggleOptionsTruthy, Falsy { truthyValue?: MaybeRefOrGetterTruthy falsyValue?: MaybeRefOrGetterFalsy }这意味着真值与假值不必是同一类型尽管实践中通常保持一致TypeScript 会依据传入的 options 自动推断value与toggle的参数/返回值类型获得完整的编译期校验。五、事件绑定的陷阱第一个参数是覆盖值useToggle文档特别标注了一个 Caution切换函数把第一个参数视为覆盖值override value。如果在模板中把函数直接传给事件浏览器会把事件对象$event当作第一个参数传入导致行为异常!-- caution: $event will be passed in -- button clicktoggleDark / !-- recommended to do this -- button clicktoggleDark() /原因是 DOM 事件回调会以event作为首个实参调用处理函数toggleDark(event)等价于「将主题强制设置为事件对象」——而事件对象恒为 truthy于是主题永远被强制切换为真值一侧再也无法翻转回来。airi 仓库中的所有使用点都严格遵守了这一约定。例如 apps/component-calling/src/App.vue 中的深色模式按钮button text-lg click() toggleDark() div v-ifisDark i-solar:moon-stars-bold-duotone / div v-else i-solar:sun-bold / /button注意这里同时展示了两种推荐写法click() toggleDark()用箭头函数包一层显式调用且不传参模板中依据isDark切换图标i-solar:moon-stars-bold-duotone与i-solar:sun-bold图标本身即是对状态的可视化反馈。在桌面端 apps/stage-tamagotchi/src/renderer/components/stage-islands/controls-island/index.vue 中控制岛的深色模式按钮同样使用了click() toggleDark()见其第 306 行toggleDark来自useTheme()解构第 40 行与 component-calling 保持一致的调用约定。为什么不直接用clicktoggleDark即使你的切换函数内部对参数做了容错直接透传函数也会让「事件对象作为覆盖值」这一隐式行为成为隐患而clicktoggleDark()或click() toggleDark()则从语法层面杜绝了误传代码意图一目了然。六、类型声明全解useToggle的完整类型签名如下理解它有助于你正确使用泛型与重载export type ToggleFn (value?: boolean) void export type UseToggleReturn [ShallowRefboolean, ToggleFn] | ToggleFn export interface UseToggleOptionsTruthy, Falsy { truthyValue?: MaybeRefOrGetterTruthy falsyValue?: MaybeRefOrGetterFalsy } export declare function useToggleTruthy, Falsy, T Truthy | Falsy( initialValue: RefT, options?: UseToggleOptionsTruthy, Falsy, ): (value?: T) T export declare function useToggle Truthy true, Falsy false, T Truthy | Falsy, ( initialValue?: T, options?: UseToggleOptionsTruthy, Falsy, ): [ShallowRefT, (value?: T) T]逐行拆解声明要素含义ToggleFn默认布尔场景下的切换函数类型(value?: boolean) voidUseToggleReturn两种形态的返回类型联合元组 或 纯函数UseToggleOptionsTruthy, Falsy自定义真值/假值选项二者均可为MaybeRefOrGetter值、ref 或 getter重载一initialValue: RefT传入 ref 时返回(value?: T) T读写的是同一个 ref重载二initialValue?: T不传或传普通值时返回[ShallowRefT, (value?: T) T]默认Truthy true、Falsy false泛型T Truthy \| Falsy状态值的类型统一为真值与假值类型的并集两个重载都遵循同样的规则切换函数的可选参数value是覆盖值——传了就强制设置不传则取反。返回值始终是新值。七、实战组合useToggleuseDark构建全端主题系统airi 将useToggle与useDark组合封装成useTheme()并在多个应用间复用是理解其工程价值的完整范例封装层packages/ui/src/composables/use-theme.tsuseDark负责「读取/持久化主题状态」含 localStorage 能力探测与 shim 兜底useToggle(isDark)负责「生成切换动作」对外暴露{ isDark, toggleDark }Web 演示层apps/component-calling/src/App.vue 与 apps/stage-web/src/App.vue消费useTheme()在 UI 上呈现当前主题并绑定切换桌面端层apps/stage-tamagotchi/src/renderer/App.vue 与 controls-island/index.vue同一套useTheme在 Electron 渲染进程中复用实现控制岛上的明暗主题按钮布局组件层packages/stage-layouts/src/components/Layouts/HeaderLink.vue 等组件通过const { isDark: dark } useTheme()只读消费主题态用于驱动背景与前景的视觉配色。该模式的价值在于状态读写点始终只有一个。无论toggleDark被多少个组件引用它操作的始终是useDark创建的同一个 ref杜绝了「各组件各自维护一份主题布尔值」导致的失步问题。八、最佳实践小结优先复用凡是「布尔或双值状态 切换」的需求先查 VueUse 是否有现成函数参见 SKILL.md 的功能表再决定是否手写传 ref 而非复制状态若状态已存在把 ref 交给useToggle让它只负责生成切换函数避免状态分裂模板中永远用clicktoggleDark()或箭头函数包裹防止事件对象被当作覆盖值传入需要自定义值时用 optionstruthyValue/falsyValue支持值、ref、getter可配合泛型获得类型推导利用返回值toggle()返回新值可无缝衔接日志、接口调用等后续逻辑封装成 composable像 airi 的useTheme()一样把「状态 切换 持久化」收敛为一个可复用函数跨 Web / Electron 端共享。掌握了useToggle的两种形态、返回值语义与事件陷阱后你会发现绝大多数「开关类」逻辑都可以在一两行内优雅地表达这正是 VueUse 组合式函数设计的核心目标——用最小的心智负担完成最频繁的状态操作。【免费下载链接】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),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Vibe-Trading OKX 现货K线数据接口实战指南:从 OHLCV 拉取、解析到分页全流程 2026/9/10 13:03:50

Vibe-Trading OKX 现货K线数据接口实战指南:从 OHLCV 拉取、解析到分页全流程

Vibe-Trading OKX 现货K线数据接口实战指南:从 OHLCV 拉取、解析到分页全流程 【免费下载链接】Vibe-Trading "Vibe-Trading: Your Personal Trading Agent" 项目地址: https://gitcode.com/GitHub_Trending/vi/Vibe-Trading 本文以 Vibe-Trading …

阅读更多 →
ESP32与MQTT协议实现温湿度数据上云实战 2026/9/10 13:03:50

ESP32与MQTT协议实现温湿度数据上云实战

1. 项目概述:MQTT温湿度数据上云方案设计 去年帮一家农业大棚做环境监控系统时,我第一次将ESP32温湿度传感器通过MQTT协议接入OneNet平台。这个看似简单的物联网项目,在实际部署中遇到了协议配置、数据解析、网络稳定性等系列问题。本文将分享…

阅读更多 →
STM32L031硬件I2C驱动VL53L0X低功耗激光测距实战解析 2026/9/10 13:03:50

STM32L031硬件I2C驱动VL53L0X低功耗激光测距实战解析

简介:STM32L031与VL53L0X激光测距传感器硬件I2C驱动包,是一份面向嵌入式初、中级开发者及物联网项目工程师的完整工程资源。资源以Keil MDK工程组织,围绕STM32L0系列超低功耗MCU与VL53L0X ToF测距芯片展开,涵盖I2C初始化、传感器寄…

阅读更多 →
oh-my-pi 内置规则剖析:为什么 TypeScript 中禁止滥用 `isRecord` 类型守卫,以及正确的边界解析姿势 2026/9/10 13:03:50

oh-my-pi 内置规则剖析:为什么 TypeScript 中禁止滥用 `isRecord` 类型守卫,以及正确的边界解析姿势

oh-my-pi 内置规则剖析:为什么 TypeScript 中禁止滥用 isRecord 类型守卫,以及正确的边界解析姿势 【免费下载链接】oh-my-pi ⌥ Coding agent with the IDE wired in 项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi 本文以 oh-my-p…

阅读更多 →
RustFS e2e_test 端到端测试套件深入指南:架构、运行方式与 CI 编排 2026/9/10 13:03:50

RustFS e2e_test 端到端测试套件深入指南:架构、运行方式与 CI 编排

RustFS e2e_test 端到端测试套件深入指南:架构、运行方式与 CI 编排 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting migrati…

阅读更多 →
工程车辆目标检测数据集:1类挖掘机+1000张真实工况图像 2026/9/10 13:00:50

工程车辆目标检测数据集:1类挖掘机+1000张真实工况图像

简介:本资源是一个专为工程车辆目标检测任务构建的高质量已标注图像数据集,面向计算机视觉方向的研究人员、算法工程师及深度学习初学者,助力自动驾驶、智能工地监控与交通安全管理等场景下的模型训练与验证。数据集包含1000张JPG格式工程车辆…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞