Vue3 ref属性详解:响应式引用与类型安全实践

1. Vue3中ref属性的核心概念解析

在Vue3的响应式系统中,ref是最基础也最重要的响应式API之一。与Vue2时代不同,Vue3的ref可以同时作用于原生HTML元素和自定义组件实例,这种统一的设计极大简化了开发者的心智负担。

ref本质上是一个响应式引用,它会将一个普通值包装成响应式对象。这个对象有一个.value属性,通过这个属性我们可以访问或修改内部的值。当我们在模板中使用ref时,Vue会自动处理.value的访问,这使得模板中的写法更加简洁。

javascript复制import { ref } from 'vue'

// 基本类型的ref
const count = ref(0)
console.log(count.value) // 0

// 对象类型的ref
const user = ref({ name: 'John' })
console.log(user.value.name) // John

在模板中使用ref时,我们通过特殊的ref属性来标记需要引用的元素或组件:

html复制<template>
  <!-- 引用HTML元素 -->
  <input ref="inputRef" type="text">
  
  <!-- 引用组件实例 -->
  <MyComponent ref="componentRef" />
</template>

<script setup>
import { ref, onMounted } from 'vue'

const inputRef = ref(null)
const componentRef = ref(null)

onMounted(() => {
  // 访问DOM元素
  inputRef.value.focus()
  
  // 访问组件实例
  componentRef.value.someMethod()
})
</script>

1.1 ref在HTML元素上的使用细节

当ref用于原生HTML元素时,它引用的是实际的DOM元素。这在需要直接操作DOM的场景下非常有用,比如:

  • 手动聚焦输入框
  • 测量元素尺寸
  • 集成第三方DOM库
html复制<template>
  <div ref="container">...</div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const container = ref(null)

onMounted(() => {
  console.log(container.value.offsetWidth) // 获取元素宽度
})
</script>

需要注意的是,ref引用的DOM元素只能在组件挂载后才能访问,因此通常在onMounted生命周期钩子中操作它们。

1.2 ref在组件上的特殊行为

当ref用于自定义组件时,它引用的是组件的实例。这为父组件访问子组件的属性和方法提供了途径:

html复制<!-- ChildComponent.vue -->
<script setup>
const sayHello = () => console.log('Hello from child!')
defineExpose({
  sayHello
})
</script>

<!-- ParentComponent.vue -->
<template>
  <ChildComponent ref="childRef" />
</template>

<script setup>
import { ref, onMounted } from 'vue'

const childRef = ref(null)

onMounted(() => {
  childRef.value.sayHello() // 调用子组件方法
})
</script>

在Vue3的