小程序中获取元素节点

💡 前言

在 Web 环境中,我们常用以下方式获取 DOM 元素:

复制代码
document.querySelector()
document.getElementById()
this.$refs.xxx

但在 小程序uni-app 环境中,这些方法统统失效!

因为小程序中没有浏览器 DOM,也不存在 documentwindow 这类全局对象。

👉 换句话说:
小程序没有 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.myView
    const 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 同样可用(仅限自定义组件)
不存在的对象 windowdocumentHTMLElement ❌ 无法使用

🧩 五、实战示例:滚动到指定元素

复制代码
<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)
  }
}

⚡ 注意事项

  1. 必须等待渲染完成后调用mountedonReady);

  2. 查询链式调用最后必须执行 .exec()

  3. 如果使用 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 操作的核心手段。

相关推荐
G_G#4 分钟前
纯前端js插件实现同一浏览器控制只允许打开一个标签,处理session变更问题
前端·javascript·浏览器标签页通信·只允许一个标签页
@大迁世界19 分钟前
TypeScript 的本质并非类型,而是信任
开发语言·前端·javascript·typescript·ecmascript
GIS之路28 分钟前
GDAL 实现矢量裁剪
前端·python·信息可视化
是一个Bug32 分钟前
后端开发者视角的前端开发面试题清单(50道)
前端
Amumu1213834 分钟前
React面向组件编程
开发语言·前端·javascript
持续升级打怪中1 小时前
Vue3 中虚拟滚动与分页加载的实现原理与实践
前端·性能优化
GIS之路1 小时前
GDAL 实现矢量合并
前端
hxjhnct1 小时前
React useContext的缺陷
前端·react.js·前端框架
前端 贾公子1 小时前
从入门到实践:前端 Monorepo 工程化实战(4)
前端
说私域1 小时前
短视频私域流量池的变现路径创新:基于AI智能名片链动2+1模式S2B2C商城小程序的实践研究
大数据·人工智能·小程序