在uniapp + Vue3 + TypeScript中,ref在onMounted中拿不到元素,通常有以下几种原因:
1. 组件未挂载完成
onMounted虽然表示组件已挂载,但DOM渲染可能需要额外时间:
import { ref, onMounted, nextTick } from 'vue'
const myRef = ref<HTMLElement | null>(null)
onMounted(() => {
  // 立即访问可能拿不到
  console.log(myRef.value) // 可能为null
  
  // 使用 nextTick 确保DOM更新完成
  nextTick(() => {
    console.log(myRef.value) // 正常获取元素
  })
})
2. 条件渲染导致元素不存在
元素在条件渲染中可能还未显示:
const showElement = ref(false)
const myRef = ref<HTMLElement | null>(null)
onMounted(() => {
  // 如果元素初始不显示,ref为null
  console.log(myRef.value) // null
  
  // 显示元素后再获取
  showElement.value = true
  nextTick(() => {
    console.log(myRef.value) // 正常获取
  })
})
3. Ref名称拼写错误
确保模板中的ref名称与脚本中一致:
<template>
  <!-- 正确 -->
  <view ref="myRef"></view>
  
  <!-- 错误:名称不匹配 -->
  <view ref="myref"></view>
</template>
<script setup lang="ts">
const myRef = ref(null) // 模板中必须是 myRef
</script>
4. 在自定义组件上使用ref
在自定义组件上使用ref获取的是组件实例,而非DOM元素:
<template>
  <!-- 获取组件实例 -->
  <MyComponent ref="compRef" />
  
  <!-- 获取DOM元素需要指定ref -->
  <view ref="domRef"></view>
</template>
<script setup lang="ts">
const compRef = ref() // 组件实例
const domRef = ref<HTMLElement | null>(null) // DOM元素
</script>
解决方案总结:
- 使用nextTick确保DOM更新完成
- 检查条件渲染逻辑
- 验证ref名称一致性
- 区分组件ref和DOM ref
使用nextTick是最常见的解决方案。