资讯动态

Vant `useRect` 组合式函数完全指南:获取元素尺寸与视口相对位置

发布时间:2026/9/12 21:28:17 来源:尧图企业网站定制
VantuseRect组合式函数完全指南获取元素尺寸与视口相对位置【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vantuseRect是vant/use提供的一个轻量级组合式函数Composable用于获取任意 DOM 元素的尺寸以及该元素相对于浏览器视口viewport的位置其行为等价于原生Element.getBoundingClientRect()。它被广泛用于 Vant 组件库内部如 Sticky、List、Calendar、DropdownMenu、IndexBar 等组件以完成布局测量与滚动联动本文将从基础用法、API 声明、源码实现到组件级实战应用带你完整掌握这一工具。功能概述useRect的核心价值在于在 Vue 3 的组合式 API 环境下以统一的接口读取元素的布局信息。它的输入既可以是 DOM 元素本身也可以是 Vue 的ref引用内部通过unref自动解包调用方无需关心传参形态同时它还额外处理了Window对象与元素尚未挂载两种边界情况避免直接调用getBoundingClientRect时的各种坑。它与原生 API 的对应关系如下useRect(element)等价的原生调用传入Elementelement.getBoundingClientRect()传入RefElementunref(ref).getBoundingClientRect()传入Window基于innerWidth/innerHeight构造的DOMRect传入undefined或空 ref返回全 0 的DOMRect安装与引入vant/use已经被包含在 Vant 的依赖中但官方仍然推荐在项目中显式安装该包以便直接使用这些组合式 API详见 Composables 文档# with npm npm i vant/use # with yarn yarn add vant/use # with pnpm pnpm add vant/use # with Bun bun add vant/use安装完成后从包入口导入即可useRect由 入口文件 统一导出import { useRect } from vant/use;基础用法传入元素引用ref在模板中给目标元素绑定ref然后在onMounted生命周期中调用useRect此时元素已完成挂载测量才有意义div refroot /import { ref, onMounted } from vue; import { useRect } from vant/use; export default { setup() { const root ref(); onMounted(() { const rect useRect(root); console.log(rect); // - the size of an element and its position relative to the viewport }); return { root }; }, };传入原始 DOM 元素也可以直接传入元素实例这在事件回调、指令或第三方库集成场景中很常见import { useRect } from vant/use; const el document.querySelector(.my-element); const rect useRect(el);传入 Window 对象useRect也接受Window此时返回的是整个窗口的尺寸top、left恒为 0import { useRect } from vant/use; const rect useRect(window); // rect.width window.innerWidth // rect.height window.innerHeightAPI类型声明function useRect( element: Element | Window | RefElement | Window | undefined, ): DOMRect;参数element支持三种形态Element直接传入 DOM 元素Window传入全局window对象RefElement | Window | undefinedVue 的 ref 引用元素可能暂未挂载值为undefined。返回值统一为标准的DOMRect对象。返回值名称说明类型width元素的宽度numberheight元素的高度numbertop元素顶部到视口顶部的距离numberleft元素左侧到视口左侧的距离numberright元素右侧到视口左侧的距离即left widthnumberbottom元素底部到视口顶部的距离即top heightnumber注意top/left表示的是元素边框到视口边缘的距离而right/bottom是到视口左上角的绝对坐标并非元素到视口右边/下边的距离。这与原生getBoundingClientRect()的语义完全一致页面发生滚动时这些值会随之变化。源码实现深度解析useRect的实现非常精简完整源码位于 packages/vant-use/src/useRect/index.ts。理解它的三个分支有助于你在边界场景下正确使用import { Ref, unref } from vue; const isWindow (val: unknown): val is Window val window; const makeDOMRect (width: number, height: number) ({ top: 0, left: 0, right: width, bottom: height, width, height, }) as DOMRect; export const useRect ( elementOrRef: Element | Window | RefElement | Window | undefined, ) { const element unref(elementOrRef); if (isWindow(element)) { const width element.innerWidth; const height element.innerHeight; return makeDOMRect(width, height); } if (element?.getBoundingClientRect) { return element.getBoundingClientRect(); } return makeDOMRect(0, 0); };1.unref自动解包 ref首行调用 Vue 的unref如果传入的是 ref则取其.value如果传入的是普通元素或Window则原样返回。这正是传元素或传 ref 皆可这一便利性的来源。2.Window特殊分支isWindow通过val window严格判断。由于window对象自身没有getBoundingClientRect方法如果直接调用会抛出TypeError因此源码用innerWidth/innerHeight构造了一个DOMRect此时top、left为 0right等于窗口宽度bottom等于窗口高度。3.getBoundingClientRect主路径对于普通元素直接返回element.getBoundingClientRect()的结果确保返回值与原生 API 完全一致包含x、y等全部标准字段。4. 全零兜底当传入undefined例如 ref 尚未绑定到已挂载元素或元素被销毁时返回一个width、height、top、left、right、bottom全部为 0 的DOMRect保证调用方无需做空值判断也不会因调用不存在的方法而抛错。在 Vant 组件中的真实应用useRect不是孤立存在的工具函数Vant 大量组件都基于它完成布局测量。以下是两个具有代表性的应用场景。场景一Sticky 吸顶组件的定位判断在 Sticky 组件 中滚动事件回调onScrollSticky.tsx通过useRect同时测量根元素与容器元素的位置决定是否进入fixed吸顶状态const onScroll () { if (!root.value || isHidden(root)) { return; } const { container, position } props; const rootRect useRect(root); const scrollTop getScrollTop(window); state.width rootRect.width; state.height rootRect.height; if (position top) { if (container) { const containerRect useRect(container); const difference containerRect.bottom - offset.value - state.height; state.fixed offset.value rootRect.top containerRect.bottom 0; state.transform difference 0 ? difference : 0; } else { state.fixed offset.value rootRect.top; } } // ... };这里rootRect.width被用于同步吸顶时占位元素的宽度避免页面布局抖动rootRect.top与containerRect.bottom则分别驱动吸顶触发与容器内回收。窗口尺寸变化时Sticky.tsx组件同样依赖useRect(root)重新测量保证吸顶宽度跟随响应式布局更新。场景二动态高度测量use-height组合式函数 封装了元素高度自动追踪逻辑其核心正是useRectconst setHeight () { height.value useRect(element).height; };它会在onMounted、Popup 重新打开、窗口尺寸变化等时机反复调用useRect刷新高度值并在需要适配安全区safe area时通过定时器补偿 iOS 上首屏高度测量不准的问题。更多使用位置通过源码检索可以发现useRect还被下列组件直接引用覆盖滚动联动、弹层定位、懒加载检测等场景List.tsx列表滚动加载时的占位与状态判断Calendar.tsx 与 CalendarMonth.tsx日历滚动定位DropdownMenu.tsx 与 DropdownItem.tsx下拉菜单的弹出层定位IndexBar.tsx 与 IndexAnchor.tsx索引栏锚点定位FloatingBubble.tsx、Signature.tsx、SwipeCell.tsx 等。这些组件在渲染与交互的关键路径上调用useRect验证了它在真实业务中的高频价值。使用注意事项与最佳实践在挂载后再测量getBoundingClientRect要求元素存在于文档中。请务必在onMounted或nextTick之后调用否则空 ref 会走全零兜底分支得到width: 0、height: 0。与滚动的关系返回值是相对视口的坐标页面滚动会导致top/left变化。若需要元素在文档中的绝对位置需叠加滚动偏移量。避免在布局抖动中高频调用getBoundingClientRect会强制浏览器进行样式计算与布局reflow在滚动事件中频繁调用可能影响性能。可参考 Sticky 组件仅在scroll事件回调中测量其余时机复用缓存值的做法。隐藏元素返回 0使用display: none等隐藏元素测量结果恒为 0Vant 的isHidden工具会配合跳过此类场景如果你需要测量隐藏元素的尺寸请先使其可见。服务端渲染SSR注意useRect依赖window与 DOM API仅应在客户端执行。若需在 SSR 环境下使用应将其放入onMounted等客户端生命周期中避免在服务端渲染阶段直接调用。总结useRect用不到 20 行代码为 Vue 开发者提供了对getBoundingClientRect的优雅封装自动解包 ref、兼容Window、空值兜底返回值保持标准DOMRect语义。无论是独立业务开发中的元素测量还是深入阅读 Vant 源码时理解 Sticky、List、DropdownMenu 等组件的定位逻辑掌握它都能让你的 Vue 3 开发事半功倍。若想系统了解vant/use提供的其他组合式 API如useScrollParent、useCountDown、useEventListener等可参阅 Composables 总览文档。【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价