在 airi 中使用 VueUse useFocus:DOM 元素焦点状态追踪与双向控制实战

在 airi 中使用 VueUse useFocus:DOM 元素焦点状态追踪与双向控制实战 在 airi 中使用 VueUse useFocusDOM 元素焦点状态追踪与双向控制实战【免费下载链接】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导读本文围绕 VueUse 的useFocus组合式函数展开讲解如何在 Vue 3 / Nuxt 项目中以响应式方式追踪、读取并主动设置 DOM 元素的焦点focus状态。结合 airi 开源仓库一个自托管、面向 Web / macOS / Windows 的陪伴型 AI 项目采用 Vue 3 Vite pnpm workspace 架构的实际工程环境你将掌握useFocus的调用方式、initialValue与focusVisible等核心选项的含义以及用它替代手工操作focus()/blur()事件监听来管理输入框、搜索框、弹窗等交互焦点的实战方案。在 airi 工程中的适用场景airi 的各个前端应用如 apps/stage-web、apps/stage-pocket以及舞台相关 UI 组件库如 packages/stage-ui均基于 Vue 3 构建并在依赖中引入了vueuse/core参见 apps/stage-web/package.json 中的vueuse/core: catalog:由仓库根目录 pnpm-workspace.yaml 的 catalog 统一管理版本。当你在这些应用里需要实现以下交互时useFocus是首选方案语音/文字输入框的自动聚焦与失焦状态检测聊天输入区在点击按钮后聚焦、提交后失焦的完整状态机弹窗或设置面板打开时将焦点交给第一个可聚焦控件根据焦点状态动态切换输入框的高亮样式对应 CSS 的:focus-visible行为。.agents/skills/vueuse-functions/SKILL.md中也将useFocus归入Sensors传感器类别标注调用规则为AUTO——即在合适的场景下应优先使用该组合式函数而非手写事件监听代码以保持实现的简洁、可维护与高性能。基本用法响应式追踪焦点状态useFocus的核心价值在于把一个普通 DOM 元素变成一个可读可写的响应式焦点状态。它返回一个focused的WritableComputedRefboolean——读取时反映目标元素当前是否拥有焦点写入时则会真正触发元素的focus()或blur()。最基本的使用方式如下与文档 useFocus.md 中的示例一致import { useFocus } from vueuse/core const target shallowRef() const { focused } useFocus(target) watch(focused, (focused) { if (focused) console.log(input element has been focused) else console.log(input element has lost focus) })几个关键点target通过shallowRef()声明并在模板中通过reftarget绑定到真实元素useFocus接受MaybeElementRef即它可以接收 ref、getter 或直接的元素引用。focused是可写的计算引用focused.value为true表示元素当前被聚焦为false表示失焦。你无需手动添加focus/blur事件监听器useFocus内部会为你完成事件绑定与清理避免内存泄漏。首次渲染自动聚焦initialValue 选项如果希望在元素首次渲染时就获得焦点可以传入initialValue: true。该选项会在目标元素就绪后主动触发一次focus事件import { useFocus } from vueuse/core const target shallowRef() const { focused } useFocus(target, { initialValue: true })这对页面打开即聚焦输入框的场景非常实用例如 airi 的聊天对话框打开后立即聚焦消息输入区用户无需再点击输入框即可直接打字。由外部动作改变焦点状态focused的双向性意味着你可以通过任何响应式逻辑来控制焦点。下面的例子展示了点击按钮后让下方输入框获得焦点与文档 useFocus.md 中的 Vue 单文件组件示例一致script setup langts import { useFocus } from vueuse/core import { shallowRef } from vue const input shallowRef() const { focused } useFocus(input) /script template div button typebutton clickfocused true Click me to focus input below /button input refinput typetext /div /template当focused被赋值为true时useFocus会调用目标元素的focus()赋值为false时则调用blur()。这一机制让你可以把是否聚焦提升为应用状态的一部分——例如在弹窗关闭、路由切换或语音唤醒等事件中统一管理焦点归属而不是散落各处的document.querySelector().focus()调用。选项与类型声明全解从文档 useFocus.md 的类型声明部分useFocus的完整签名如下export interface UseFocusOptions extends ConfigurableWindow { /** * Initial value. If set true, then focus will be set on the target * * default false */ initialValue?: boolean /** * Replicate the :focus-visible behavior of CSS * * default false */ focusVisible?: boolean /** * Prevent scrolling to the element when it is focused. * * default false */ preventScroll?: boolean } export interface UseFocusReturn { /** * If read as true, then the element has focus. If read as false, then the element does not have focus * If set to true, then the element will be focused. If set to false, the element will be blurred. */ focused: WritableComputedRefboolean } export declare function useFocus( target: MaybeElementRef, options?: UseFocusOptions, ): UseFocusReturn三个选项的实战含义选项默认值作用initialValuefalse为true时元素首次渲染后立即聚焦focusVisiblefalse为true时复刻 CSS 的:focus-visible语义仅在键盘导航如 Tab 键触发的聚焦下才将focused置为true鼠标点击聚焦不会触发preventScrollfalse为true时聚焦元素时阻止浏览器滚动到该元素内部透传给focus({ preventScroll: true })适合弹窗/抽屉等不希望页面跳动的内容区需要说明的是focusVisible: true需要浏览器支持:focus-visible相关 API在不支持的环境下会回退为普通聚焦行为。ConfigurableWindow扩展自vueuse/core的窗口配置通常无需显式指定。与其他 VueUse 函数的配合useFocus是 VueUse 焦点管理族的一员可根据需求组合使用useActiveElement响应式追踪document.activeElement可与useFocus配合判断当前焦点元素与目标元素是否一致useFocusWithin追踪元素或其任意后代是否拥有焦点适合下拉面板、组合输入框等含多个子控件的场景useFocusTrap在弹窗/模态框中锁定焦点循环防止 Tab 焦点逃逸到背景层该函数为Integrations类别的外部依赖包装器。在 airi 的 Live2D 舞台场景中也可以看到焦点/坐标类响应式推导的同类实践packages/stage-ui-live2d/src/composables/live2d/eye-tracking.ts中的useLive2DEyeFocusFor通过computed把鼠标光标坐标映射为 Live2D 模型的视线焦点Live2DModel.focus(x, y)并在packages/stage-ui-live2d/src/components/scenes/Live2D.vue#L58与:focus-at绑定。这展示了 airi 项目中以响应式推导取代命令式更新的一贯风格useFocus正是这一思想在 DOM 焦点管理上的体现。在 airi 聊天输入场景的落地示例结合 airi 这类陪伴型 AI 应用的实际交互下面给出一个语音唤醒后自动聚焦输入框按下回车发送后失焦的完整示例script setup langts import { useFocus } from vueuse/core import { ref, shallowRef } from vue const inputEl shallowRefHTMLInputElement() const { focused } useFocus(inputEl, { initialValue: true }) const message ref() function onVoiceWakeup() { focused.value true // 语音唤醒后立即聚焦输入框 } function onSend() { // ... 发送逻辑 focused.value false // 发送后收起键盘焦点 } /script template div classchat-box clickfocused true input refinputEl v-modelmessage typetext placeholder输入消息… :class{ input-focus-visible: focused } keyup.enteronSend /div /template这段代码集中体现了useFocus的全部优势状态即数据、数据驱动行为既无需手写事件监听又天然与 Vue 的响应式体系watch、computed、模板绑定无缝集成。小结useFocus(target)返回可读可写的focused引用读反映焦点、写触发focus()/blur()三个核心选项initialValue首次渲染聚焦、focusVisible复刻:focus-visible、preventScroll聚焦不滚动结合watch、模板绑定或外部事件按钮、语音唤醒、弹窗打开即可构建完整的焦点状态机如需更复杂的焦点管理可组合useActiveElement、useFocusWithin、useFocusTrap。仓库中该函数的完整参考文档位于 .agents/skills/vueuse-functions/references/useFocus.md其所属技能的总览与函数索引见 .agents/skills/vueuse-functions/SKILL.md配合 apps/stage-web/package.json 中vueuse/core的依赖声明即可在 airi 的任何 Vue 应用中直接开始使用。【免费下载链接】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),仅供参考