uni-app 中必须用 uni.createSelectorQuery() 异步查询 boundingClientRect,因非 H5 平台无真实 DOM,this.$refs.xxx.getBoundingClientRect() 会报错;自定义组件内需加 .in(this) 且顺序在 .select() 前;须在元素渲染及图片加载完成后调用,推荐 $nextTick + @load 钩子;批量查询时 res 数组按顺序返回,但未找到的元素为 null,须逐项判空。
boundingclientrect 在 uni-app 中不是直接调用 dom 方法,而是必须通过 uni.createselectorquery() 异步查询,否则会返回 null 或尺寸为 0。
为什么直接用 getBoundingClientRect() 会报错或返回空?
uni-app 的 Vue 组件在非 H5 平台(如微信小程序、App)中不运行在真实 DOM 环境下,this.$refs.xxx.getBoundingClientRect() 在小程序端根本不存在,调用会报 undefined is not a function;H5 虽然能用,但跨平台代码会断裂。统一走 uni.createSelectorQuery() 是唯一可靠路径。
自定义组件内必须加 .in(this)
在 .vue 文件的自定义组件中,若不显式指定作用域,查询会默认在页面级执行,找不到组件内部的元素。
- ✅ 正确写法:
uni.createSelectorQuery().in(this).select('.my-box').boundingClientRect(...).exec() - ❌ 错误写法:
uni.createSelectorQuery().select('.my-box')...(组件内大概率查不到) - ⚠️ 注意:
.in(this)必须在.select()之前链式调用,顺序不能颠倒
什么时候调用才不会拿到 0 高度?
元素必须已渲染完成,且内容(尤其是图片、异步加载区块)已 layout 完毕。常见踩坑点:
- 在
onLoad里调用 → 元素可能还没挂载,data为空 - 在
onReady里调用 → 大部分情况够用,但含图片时仍可能因图片未解码而高度不准 - ✅ 更稳妥做法:结合
$nextTick+ 图片加载完成钩子(如@load)再查一次,或用setTimeout延迟 100ms(仅临时调试) - ? 小程序平台对图片加载有缓存和懒加载机制,单纯等
onReady不等于视觉布局就绪
多元素批量查询与错误处理
一次查多个元素可复用同一个 query 实例,但要注意回调中结果顺序与 select 调用顺序一致,且任一元素未找到会导致对应位置为 null。
const query = uni.createSelectorQuery().in(this);
query.select('#header').boundingClientRect();
query.select('#content').boundingClientRect();
query.select('#footer').boundingClientRect();
query.exec(res => {
// res 是数组,按 select 顺序排列:[headerData, contentData, footerData]
if (!res[0] || !res[1]) {
console.warn('至少一个元素未查询到,请检查 ID 是否存在或是否已渲染');
return;
}
const totalHeight = res[0].height + res[2].height;
that.scrollableHeight = uni.getSystemInfoSync().windowHeight - totalHeight - 30;
});
真正容易被忽略的是:res 数组长度一定等于 select 次数,但每个项可能是 null —— 不是抛错,也不报 warning,静默失败。务必逐项判空,否则后续计算会 NaN。


















