ARTICLE DETAIL

资讯详情

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

VueUse useActiveElement 完全指南:响应式追踪当前聚焦元素

VueUse useActiveElement 完全指南:响应式追踪当前聚焦元素 前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载useActiveElement是 VueUse 中一个轻量的 Elements 类组合式函数它以响应式的方式暴露document.activeElement并在页面焦点变化时自动更新返回值。无论你是在构建无障碍提示、快捷键面板、自定义表单组件还是需要感知用户此刻正在与哪个 DOM 节点交互useActiveElement都能以极少的代码提供可靠的焦点追踪能力。读完本文你将掌握它的基础用法、Shadow DOM 穿透策略、元素移除监听以及组件式调用方式。快速上手useActiveElement的用法非常直观调用后得到一个ShallowRef其值始终指向当前文档中处于激活状态的元素。script setup langts import { useActiveElement } from vueuse/core import { watch } from vue const activeElement useActiveElement() watch(activeElement, (el) { console.log(focus changed to, el) }) /script在默认行为下该函数会在初始化时立即读取一次document.activeElement并在随后的blur/focus事件中持续同步最新值。官方演示demo.vue展示了更贴近实战的场景页面上排列多个输入框每次切换焦点时当前激活元素的data-id都会实时显示出来这正是它最典型的使用方式。返回值与响应式原理从类型定义看useActiveElement返回的是一个ShallowRefT | null | undefined见 index.ts。这意味着它是一个浅层 ref值本身不会做深层的递归响应式代理适合存放 DOM 节点这类引用类型当没有任何元素聚焦例如焦点落在document.body或页面本身时值可能是null、undefined或body元素使用前需要做好判空。源码中更新值的核心逻辑index.ts如下const getDeepActiveElement () { let element document?.activeElement if (deep) { while (element?.shadowRoot) element element?.shadowRoot?.activeElement } return element } const trigger () { activeElement.value getDeepActiveElement() as T | null | undefined }监听事件时采用了capture: true与passive: true两个监听选项index.tscapture捕获阶段监听让焦点事件在最早期被捕获避免某些组件内部调用stopPropagation后导致焦点变化无法被感知passive被动监听告知浏览器该监听器不会调用preventDefault有助于提升滚动与事件处理性能。一个值得注意的细节是blur事件处理函数中的判断逻辑useEventListener( window, blur, (event) { if (event.relatedTarget ! null) return trigger() }, listenerOptions, )blur事件的relatedTarget表示焦点转移到的目标元素。只有当relatedTarget null即焦点完全离开了当前文档、而不是在文档内部元素间转移时才触发更新避免在焦点于页面内移动时做无意义的重复赋值。选项Options详解useActiveElement的选项类型为UseActiveElementOptionsindex.ts它继承了 VueUse 通用的ConfigurableWindow与ConfigurableDocumentOrShadowRoot定义见 _configurable.ts。完整选项如下选项类型默认值说明deepbooleantrue是否向 Shadow DOM 内部深度查找真正激活的元素triggerOnRemovalbooleanfalse当前激活元素被移出 DOM 时是否触发一次更新内部基于MutationObserverwindowWindowdefaultWindow自定义window实例例如在 iframe 或测试环境中使用documentDocumentOrShadowRootwindow.document自定义document实例或 Shadow Root其中window与document均来自 VueUse 的可配置Configurable设计体系在 SSR 环境下defaultWindow会被定义为undefined_configurable.ts因此函数在服务端不会注册任何监听器也不会抛错可以安全地在同构应用中调用。深入 Shadow DOMdeep选项Web Components 的 Shadow DOM 是封装样式的利器但也会带来一个经典问题document.activeElement只返回最外层的 shadow host而无法直接暴露 shadow 树内部真正获得焦点的元素。默认情况下deep: true会让useActiveElement通过while (element?.shadowRoot)循环持续下钻沿着shadowRoot.activeElement一路找到最深层激活的元素。若你想只拿到 shadow host 本身例如仅需判断焦点是否落在某个自定义组件上将deep设为false即可import { useActiveElement } from vueuse/core // Only get the shadow host, not the element inside shadow DOM const activeElement useActiveElement({ deep: false })对应的浏览器测试index.browser.test.ts专门构造了一个attachShadow({ mode: open })的宿主节点并验证了以下行为初始化时返回document.bodyindex.browser.test.ts元素已处于聚焦状态时再调用函数能正确初始化捕获到该元素index.browser.test.ts传入自定义document: shadowRoot后focus shadow 内部的输入框也能被正确追踪index.browser.test.ts。追踪元素移除triggerOnRemoval选项浏览器原生存在一个棘手的问题当当前激活元素被从 DOM 中移除时document.activeElement通常会回退到body但原生focus/blur事件可能不会触发导致响应式状态无法自动刷新。triggerOnRemoval: true正是为弥补这一盲区而设计的import { useActiveElement } from vueuse/core const activeElement useActiveElement({ triggerOnRemoval: true })该选项的底层实现是 VueUse 的另一个独立组合式函数onElementRemovalonElementRemoval/index.ts。其原理可概括为三步通过watchEffect解包并取得当前激活元素unrefElement(target)在document上挂载一个MutationObserver配置为childList: true, subtree: true监听整棵 DOM 树的节点增删遍历每条MutationRecord的removedNodes若被移除的节点就是目标元素本身或其祖先包含目标元素则触发回调刷新activeElement的值onElementRemoval/index.ts。测试用例验证了这一行为index.browser.test.ts在普通document下激活元素被input.remove()移除后activeElement会更新为document.body在自定义shadowRoot下shadowInput被移除后activeElement更新为null。注意triggerOnRemoval依赖MutationObserver其开销与观察的 DOM 规模相关。对于焦点变化频繁、且不关心元素移除场景的应用保持默认的false即可获得最佳性能。组件式用法UseActiveElement除了组合式函数useActiveElement还以组件形式UseActiveElement提供组件实现见 component.ts并通过 packages/components/index.ts 对外导出。组件通过默认插槽暴露响应式的element数据template UseActiveElement v-slot{ element } Active element is {{ element?.dataset.id }} /UseActiveElement /template从源码可以看出component.ts组件接收的 props 与组合式函数的选项一一对应deep、triggerOnRemoval、window、document全部透传给内部的useActiveElement(props)。因此所有上述配置能力在组件形态下同样可用非常适合在纯模板场景或无需script setup的项目中使用。与其他组合式函数的联动useActiveElement是 VueUse 焦点体系中的基础构件常被其他函数复用。例如useFocusWithinuseFocusWithin/index.ts就基于它判断焦点是否位于目标元素内部。你可以用类似思路组合出更复杂的行为比如import { useActiveElement } from vueuse/core import { useFocusWithin } from vueuse/core const activeElement useActiveElement()例如在构建可搜索的输入建议框时结合useActiveElement判断焦点是否离开了输入框与下拉列表从而决定是否收起建议面板。导出位置与适用范围useActiveElement从vueuse/core包导出导出声明位于 packages/core/index.ts组件版UseActiveElement从vueuse/components包导出声明位于 packages/components/index.ts底层依赖onElementRemoval与useEventListener同样位于 packages/core 目录内可在需要时独立复用。该函数属于浏览器环境Elements 类别能力其焦点追踪依赖 DOM 事件因此主要服务于客户端渲染场景得益于defaultWindow的 SSR 保护在同构应用中调用也不会产生副作用源码标注了__NO_SIDE_EFFECTS__见 index.ts。总结useActiveElement用一个简洁的 API 封装了浏览器焦点追踪中最容易被忽视的细节capture阶段的事件捕获、Shadow DOM 的深度穿透、以及元素移除时的事件盲区补偿。理解其选项背后的实现机制能帮助你在构建交互复杂的前端应用时精准把握用户正在与哪个元素交互这一关键状态并写出既简洁又健壮的焦点相关逻辑。赞分享前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载相关推荐VueUse useActiveElement 实战指南在 Airi 中响应式追踪焦点元素与 Shadow DOM 深度遍历VueUse useActiveElement 实战指南在 Airi 中响应式追踪焦点元素与 Shadow DOM 深度遍历 导读 useActiveElemAI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染airi 项目实战用 VueUse useElementHover 响应式追踪元素悬停状态airi 项目实战用 VueUse useElementHover 响应式追踪元素悬停状态 本文以 airi 仓库内 .agents/skills/vueusAI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染airi 中基于 VueUse useMouseInElement 的元素内鼠标位置响应式追踪实战指南airi 中基于 VueUse useMouseInElement 的元素内鼠标位置响应式追踪实战指南 导读 useMouseInElement 是 VueUsAI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染上一篇Home Assistant Overkiz 集成使用 overkiz.set_cover_position_and_tilt 动作平滑联动调整窗帘位置与倾斜角度下一篇es-toolkit/fp 的 initial() 详解在 pipe 管道中安全剔除数组最后一个元素创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表