ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

VueUse useCurrentElement:以 ref 形式获取当前组件 DOM 元素的完整指南

VueUse useCurrentElement:以 ref 形式获取当前组件 DOM 元素的完整指南 前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载useCurrentElement是 VueUse 提供的组件级工具函数用于把当前组件或指定组件实例的 DOM 元素以响应式 ref 的形式暴露出来。它底层基于 Vue 组件实例的$el属性并借助computedWithControl实现手动控制的响应式更新适用于需要直接操作根元素、测量尺寸、绑定原生事件等场景。读完本文你将掌握它的两种调用方式、返回值类型体系、底层实现原理以及多根节点等边界场景下的注意事项。基础用法获取当前组件根元素useCurrentElement最常见的用法是不传任何参数直接获取调用它的组件实例对应的根 DOM 元素import { useCurrentElement } from vueuse/core const el useCurrentElement() // ComputedRefElement在script setup中调用时它通过getCurrentInstance()拿到当前组件实例随后返回一个类型为ComputedRefElement的响应式引用。与直接在模板中绑定ref再手动获取相比它的优势是无需预先声明ref变量、无需等待onMounted并且返回值本身具备响应性——当组件挂载或更新导致根元素变化时el.value会自动刷新。仓库中的交互演示 demo.vue 展示了它的典型用法script setup langts import { useCurrentElement } from vueuse/core import { watchEffect } from vue const el useCurrentElement() watchEffect(() { console.log(Current element:, el.value) }) /script template divOpen your console.log to see the element/div /templatewatchEffect会自动追踪el.value的读取从而在元素发生变化时打印出最新的 DOM 节点。进阶用法传入指定的 Vue 组件实例除了获取当前组件自身useCurrentElement还支持传入一个指向其他子组件的 ref从而拿到该子组件的根元素script setup langts import { useCurrentElement, VueInstance } from vueuse/core import { shallowRef } from vue const componentRef shallowRefVueInstance(null as unknown as VueInstance) const el useCurrentElement(componentRef) // ComputedRefElement /script template div OtherVueComponent refcomponentRef / pHello world/p /div /template这种场景常用于父组件需要读取子组件根节点的尺寸、位置或触发子组件根元素上的操作。此时componentRef是一个指向OtherVueComponent组件实例的shallowRef而useCurrentElement会将其解析为该组件实例的根 DOM 元素。注意这里VueInstance类型同样从vueuse/core导出它实际上等价于 Vue 的ComponentPublicInstance见 unrefElement 类型定义。示例中null as unknown as VueInstance的写法只是为了在模板ref绑定之前满足 TypeScript 的非空类型要求。返回值与类型推断useCurrentElement的完整函数签名见 源码带有三层泛型export function useCurrentElement T extends MaybeElement MaybeElement, R extends VueInstance VueInstance, E extends MaybeElement MaybeElement extends T ? IsAnyR[$el] extends false ? R[$el] : T : T, ( rootComponent?: MaybeElementRefR, ) { // ... }不传参数时返回类型默认为ComputedRefElement传入组件 ref 时TypeScript 会根据组件实例$el的类型自动推断出对应的元素类型当泛型T明确指定时例如MaybeElement的子类型返回值类型会据此收窄为编写类型安全的 DOM 操作代码提供了便利。在MaybeElement类型体系中见 unrefElement/index.ts元素被定义为HTMLElement | SVGElement | VueInstance | undefined | null的联合类型这也解释了为什么在组件挂载完成前el.value可能为undefined。底层实现原理核心实现useCurrentElement的实现非常精简完整逻辑集中在 index.tsconst vm getCurrentInstance()! const currentElement computedWithControl( () null, () (rootComponent ? unrefElement(rootComponent) : vm.proxy!.$el) as E, ) onUpdated(currentElement.trigger) onMounted(currentElement.trigger) return currentElement整个实现可以拆解为三个关键环节1. 获取组件实例getCurrentInstance()是 Vue 的内部 API用于在组合式函数中拿到当前组件的实例上下文。vm.proxy!.$el即组件实例暴露的$el属性——Vue 官方文档将其定义为组件渲染的根 DOM 元素。2. 解析传入的组件 ref当传入rootComponent时使用unrefElement将组件实例 ref 解包为真正的 DOM 元素。unrefElement的实现见 unrefElement/index.ts核心只有一行export function unrefElementT extends MaybeElement(elRef: MaybeComputedElementRefT): UnRefElementReturnT { const plain toValue(elRef) return (plain as VueInstance)?.$el ?? plain }它先用toValue解包 ref 或 getter再判断目标是否为组件实例——若是则返回其$el否则原样返回即普通 DOM 元素直接透传。这也意味着传入普通元素 ref 同样可行。3. 手动控制的响应式更新这里没有使用常规的computed而是选择了computedWithControl。这个来自vueuse/shared的工具见 computedWithControl/index.ts允许显式定义计算属性的依赖源并通过返回的trigger方法手动强制刷新。为什么需要 onMounted 与 onUpdated 触发computedWithControl在创建时传入的依赖源是() null——一个永远不会变化的空依赖。这意味着计算值不会因为任何响应式数据的变化而自动重算一切更新时机都由trigger()手动掌控。useCurrentElement于是通过 Vue 的生命周期钩子来确定触发时机onMounted(currentElement.trigger)组件挂载完成后触发一次确保返回的元素不再是undefinedonUpdated(currentElement.trigger)组件每次更新如根元素被 v-if 替换、v-for重渲染等后触发保证元素引用始终指向最新的 DOM 节点。这正好对应了computedWithControl的设计哲学——显式定义计算属性的依赖与刷新时机详见 computedWithControl 文档。由于计算值本身是惰性的只要没人读取el.valuetrigger就只会把内部dirty标记置为true不会产生无谓的重算开销。测试用例验证仓库的浏览器测试 index.browser.test.ts 用两个用例印证了上述行为用例一获取当前组件根元素const wrapper mount(defineComponent({ template: p refeltest/p, setup() { const el shallowRefHTMLElement() const currentElement useCurrentElement() return { el, currentElement } }, })) expect(vm.currentElement).toBe(vm.el)模板中的refel绑定与useCurrentElement()返回的引用指向同一个p元素。用例二获取传入组件的根元素const TestVueComponent defineComponent({ setup() { /* ... */ }, template: div refrootElHello world/div, }) // 父组件中 const el shallowRef() const currentElementEl useCurrentElement(el) expect(vm.currentElementEl).toBe((vm.el as typeof TestVueComponent).rootEl) expect((vm.currentElementEl as HTMLElement).textContent).toBe(Hello world)父组件传入指向TestVueComponent的 ref 后返回值与该子组件内部的根元素rootEl严格相等且能正确读取其文本内容。使用注意事项正如文档 index.md 中 Caveats 一节所强调的理解以下边界条件对正确使用至关重要挂载前的值为undefined$el在组件挂载完成之前不存在因此 ref 的值会保持undefined直到onMounted触发后才被填充。若在setup同步阶段直接读取el.value得到的是undefined请务必在生命周期钩子或异步回调中读取。单根元素组件对于只有一个根元素的组件它精确指向该根元素——这是最推荐的使用场景。文本根组件若组件的根是纯文本如渲染template中直接写死的文本则返回对应的文本节点text node而不是元素节点。多根节点组件Vue 3 支持多根组件fragment。此时$el并不是某个真实的业务元素而是 Vue 内部用来记录组件在 DOM 中位置的占位节点placeholder DOM node。对这个节点进行 DOM 操作通常没有实际意义。因此官方建议仅在组件拥有单一根元素时才使用本函数。如果需要在多根组件场景下定位某个具体子元素更稳妥的做法是改用useTemplateRef或普通的ref模板引用。实践建议替代nextTick 手动查询useCurrentElement把取根元素这件事封装成了响应式引用配合watchEffect或watch即可优雅地响应元素变化无需在多个生命周期钩子里反复赋值。配合其它 VueUse 工具拿到Element之后可以继续传给useResizeObserver、useElementBounding、useIntersectionObserver等以元素为输入的组合式函数实现自动跟踪当前组件根元素的测量与观察能力例如在v-if切换根节点后仍能保持观察目标最新。只在单根场景使用多根或纯文本根组件下请评估占位节点的语义是否符合预期避免对无意义的占位节点执行操作。类型安全充分利用其泛型推导能力传入组件 ref 时无需手动断言元素类型编译期即可获得准确的ComputedRefElement类型。useCurrentElement以极少的代码将 Vue 的$el、unrefElement与computedWithControl三个能力组合成开箱即用的组件元素访问方案是 VueUse 组件类工具中轻量而实用的一员。赞分享前端【免费下载链接】vueuseCollection of essential Vue Composition Utilities for Vue 3项目地址https://gitcode.com/gh_mirrors/vu/vueuse点击查看免费下载相关推荐VueUse useParentElement 指南获取当前组件或任意元素的父级 DOM 节点VueUse useParentElement 指南获取当前组件或任意元素的父级 DOM 节点 导读 在 Vue 3 组合式 API 开发中围绕某个元素获取前端airi 项目实战VueUse useCurrentElement 获取组件根元素并驱动响应式 DOM 操作airi 项目实战VueUse useCurrentElement 获取组件根元素并驱动响应式 DOM 操作 useCurrentElement 是 VueUAI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染VueUse unrefElement 完全指南从 Vue ref 与组件实例中获取真实 DOM 元素VueUse unrefElement 完全指南从 Vue ref 与组件实例中获取真实 DOM 元素 unrefElement 是 VueUse 核心库中一前端上一篇Visual C Redistributable AIO5步解决Windows应用程序运行库依赖问题的完整指南下一篇Mac用户必备12306ForMac抢票助手完整使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表