小程序中获取元素节点
💡 前言
在 Web 环境中,我们常用以下方式获取 DOM 元素:
document.querySelector()
document.getElementById()
this.$refs.xxx
但在 小程序 或 uni-app 环境中,这些方法统统失效!
因为小程序中没有浏览器 DOM,也不存在 document、window 这类全局对象。
👉 换句话说:
小程序没有 DOM 概念,只有“节点信息”或“组件实例”。
✅ 一句话总结
在 uni-app(包括微信小程序端) 中,要想获取页面元素或组件引用,必须使用 官方提供的节点查询 API:
uni.createSelectorQuery()
或者:
this.$refs + uni.createSelectorQuery().in(this)
🧩 一、使用 uni.createSelectorQuery() 获取节点信息
这是最通用、跨平台(H5 / App / 小程序)都能使用的方式。
📘 示例
<template><view><view id="box" class="my-box">Hello Box</view></view>
</template><script>
export default {mounted() {// 必须在节点渲染完成后(mounted / onReady)执行const query = uni.createSelectorQuery().in(this)query.select('#box').boundingClientRect(data => {console.log('节点信息:', data)/*data = {id: "box",dataset: {},left: 0,right: 375,top: 50,bottom: 150,width: 375,height: 100}*/}).exec()}
}
</script><style>
.my-box {width: 200rpx;height: 100rpx;background-color: pink;
}
</style>
📌 说明
uni.createSelectorQuery()类似于浏览器的document.querySelector();但它返回的不是 DOM 节点,而是 节点的布局信息(宽度、高度、坐标等);
查询必须在 节点渲染完成 后执行,否则会返回
null。
🧩 二、获取组件实例(类似 Vue 的 $refs)
在 uni-app 中,同样支持 Vue 的 ref 属性,但用法略有区别。
📘 示例
<template><view><custom-child ref="childRef"></custom-child><view ref="myView">我是 view 元素</view></view>
</template><script>
export default {mounted() {// ✅ 获取自定义组件实例console.log(this.$refs.childRef) // 输出组件实例// ⚠️ 获取原生节点(view 等)信息,不能直接 this.$refs.myViewconst query = uni.createSelectorQuery().in(this)query.select('#myView').boundingClientRect(res => {console.log('view 节点信息:', res)}).exec()}
}
</script>
📌 要点总结
| 类型 | 获取方式 | 可否用 $refs | 说明 |
|---|---|---|---|
自定义组件 <custom-child> | this.$refs.xxx | ✅ 可以 | 返回组件实例 |
原生节点 <view> / <scroll-view> | uni.createSelectorQuery() | ❌ 不行 | 返回节点信息对象 |
🧩 三、常见场景示例
1️⃣ 获取滚动条位置
const query = uni.createSelectorQuery().in(this)
query.select('.scroll-view').scrollOffset(res => {console.log('滚动位置:', res.scrollTop)
}).exec()
2️⃣ 获取节点尺寸、坐标
query.select('.item').boundingClientRect(res => {console.log('节点宽高:', res.width, res.height)
}).exec()
🧩 四、常见 API 对比表
| 功能 | Web 写法 | uni-app 对应写法 |
|---|---|---|
| 获取元素 | document.querySelector() | uni.createSelectorQuery() |
| 获取元素尺寸 | element.getBoundingClientRect() | .boundingClientRect() |
| 获取滚动偏移 | element.scrollTop | .scrollOffset() |
| 获取组件实例 | this.$refs.xxx | 同样可用(仅限自定义组件) |
| 不存在的对象 | window、document、HTMLElement | ❌ 无法使用 |
🧩 五、实战示例:滚动到指定元素
<template><scroll-view scroll-y :scroll-top="scrollTop"><view id="target" style="height: 800rpx; background: skyblue;">我是目标区域</view><view style="height: 800rpx; background: pink;"></view></scroll-view><button @click="goToTarget">滚动到目标</button>
</template><script>
export default {data() {return {scrollTop: 0}},methods: {goToTarget() {const query = uni.createSelectorQuery().in(this)query.select('#target').boundingClientRect(res => {this.scrollTop = res.top}).exec()}}
}
</script>
🧩 六、封装一个通用工具函数
为了简化开发,可以封装一个通用的 getElementRect() 函数:
// utils/dom.js
export function getElementRect(ctx, selector) {return new Promise(resolve => {const query = uni.createSelectorQuery().in(ctx)query.select(selector).boundingClientRect(res => {resolve(res)}).exec()})
}
使用示例:
import { getElementRect } from '@/utils/dom.js'export default {async mounted() {const rect = await getElementRect(this, '#myBox')console.log('元素位置与尺寸:', rect)}
}
⚡ 注意事项
必须等待渲染完成后调用(
mounted或onReady);查询链式调用最后必须执行
.exec();如果使用 Vue 3 的
<script setup>语法,可通过getCurrentInstance()获取实例:
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
const query = uni.createSelectorQuery().in(proxy)
uni.createSelectorQuery() 在 H5、App、小程序多端兼容。
🎯 总结
| 场景 | 推荐方法 |
|---|---|
| 获取节点宽高、坐标 | uni.createSelectorQuery().boundingClientRect() |
| 获取滚动位置 | .scrollOffset() |
| 获取自定义组件实例 | this.$refs.xxx |
| 组合使用(复杂页面) | uni.createSelectorQuery().in(this) |
🔁 结语:
在小程序环境中,不能直接操作 DOM。
学会使用uni.createSelectorQuery()才是真正理解小程序渲染机制的关键。
它既安全、性能稳定,又能跨多端使用,是替代 Web DOM 操作的核心手段。
