Vue 中 ref 的作用是什么?
在 Vue 中,ref 是一个非常核心的概念,根据你使用的 Vue 版本(Vue 2 或 Vue 3)以及使用场景(选项式 API 或 组合式 API),它的作用主要分为两大类:
- 用于定义响应式数据(Vue 3 组合式 API 的核心用法)。
- 用于访问 DOM 元素或子组件实例(Vue 2 和 Vue 3 通用)。
下面详细解释这两个作用:
1. 定义响应式数据 (Vue 3 Composition API)
在 Vue 3 的组合式 API(<script setup> 或 setup())中,ref 是用来创建响应式变量的主要方式之一。
- 作用: 接受一个内部值,返回一个响应式的、可变的 ref 对象。这个对象只有一个属性
.value,指向内部的值。 - 适用类型: 主要用于基本数据类型(String, Number, Boolean, null, undefined),但也可以包裹对象或数组(内部会自动调用
reactive)。 - 核心机制: 当
.value发生改变时,Vue 会自动追踪依赖并更新视图。
代码示例:
javascript
<script setup>
import { ref } from 'vue'
// 1. 定义
const count = ref(0)
const message = ref('Hello')
// 2. 在 JS/TS 中修改(必须使用 .value)
function increment() {
count.value++
console.log(count.value) // 输出新的值
}
</script>
<template>
<!-- 3. 在模板中使用(自动解包,不需要 .value) -->
<div>{{ count }}</div>
<button @click="increment">增加</button>
</template>
为什么需要 .value?
JavaScript 的基本类型(如数字、字符串)是按值传递的,不是按引用传递的。Vue 无法直接拦截基本类型的读写操作。通过将它们包裹在一个对象(ref 对象)中,Vue 就可以拦截这个对象的 .value 属性的访问和修改,从而实现响应式。
2. 访问 DOM 元素或子组件 (Template Refs)
这是 ref 最原始的用法,从 Vue 2 到 Vue 3 都存在。它允许你直接操作 DOM 或调用子组件的方法。
- 作用: 获取模板中某个 DOM 元素或子组件实例的直接引用。
- 常见场景:
- 输入框自动聚焦 (
focus())。 - 获取元素宽高、滚动位置。
- 集成第三方库(如 ECharts, D3.js, 地图 SDK),这些库通常需要原生 DOM 节点。
- 调用子组件暴露出来的方法(使用
defineExpose)。
- 输入框自动聚焦 (
Vue 3 中的用法:
你需要声明一个同名的 ref 变量,初始值为 null。当组件挂载(Mounted)后,Vue 会自动将 DOM 元素赋值给这个变量。
javascript
<script setup>
import { ref, onMounted } from 'vue'
// 1. 声明一个同名的 ref,初始为 null
const myInput = ref(null)
onMounted(() => {
// 2. 组件挂载后,myInput.value 就是原生的 input DOM 元素
myInput.value.focus()
})
</script>
<template>
<!-- 3. 在标签上通过 ref 属性绑定 -->
<input ref="myInput" />
</template>
Vue 2 中的用法(选项式 API):
javascript
// 模板中
<input ref="myInput" />
// 脚本中
this.$refs.myInput.focus()
3. 进阶:ref vs reactive (Vue 3)
在 Vue 3 中,定义响应式数据有两个主要 API:ref 和 reactive。很多初学者会困惑该用哪个。
| 特性 | ref | reactive |
|---|---|---|
| 数据类型 | 所有类型 (基本类型 + 对象) | 仅限 对象类型 (对象, 数组, Map, Set) |
| JS 中访问 | 需要 .value |
直接访问属性 |
| 模板中访问 | 自动解包 (无需 .value) |
直接访问 |
| 重新赋值 | 可以直接替换整个对象 (obj.value = {}) |
不能直接替换整个对象,否则丢失响应性 |
| 推荐程度 | 高 (官方文档和社区更倾向于主要使用 ref) | 中 (适合深层嵌套且属性明确的对象) |
总结:
- 如果你需要响应式变量(尤其是数字、字符串),用
ref。 - 如果你需要获取 DOM 元素,用
ref。 ref在 Vue 3 中是“更通用”的响应式方案。
右滑查看面试常问