从零开始学 Vue3(二):5 分钟搞懂 ref 和 reactive,再也不用死记硬背
目录
大家好,上一篇讲了为什么应该直接学 Vue3,以及 Vue3 最核心的 "响应式" 魔法。今天我们就正式开始写代码,搞定 Vue3 里最基础、最重要的两个 API:ref和reactive
很多初学者刚接触这两个东西的时候都会懵:"这俩都是干嘛的?什么时候用 ref?什么时候用 reactive?为什么 ref 还要加个.value?"
一、先搞懂一个最基本的问题
在讲 ref 和 reactive 之前,我先问你一个问题:为什么我们需要这两个东西?直接用普通的变量不行吗?
答案很简单:因为不是所有变量,Vue3 都会帮你自动更新页面。
上一篇我们说了,Vue3 的核心魔法是 "数据变了,页面自动变"。但这个魔法不是自动生效的,你得明确告诉 Vue3:"这个变量很重要,你帮我盯着它,只要它变了,就帮我更新页面。"
而ref 和 reactive,就是用来告诉 Vue3"请帮我盯着这个变量" 的工具。
换句话说:
- 普通变量:你改了它,页面不会变
- 用 ref/reactive 包装过的变量:你改了它,页面自动变
就这么简单。
二、第一个工具:ref
ref是 Vue3 里最常用的 API,没有之一。它用来创建响应式的简单数据。
什么是简单数据?就是数字、字符串、布尔值这种单个的值。
1. ref 的基本用法
我们还是用计数器的例子,一步一步来:
第一步:从 vue 里导入 ref
import { ref } from 'vue'
第二步:用 ref 创建一个响应式变量
const count = ref(0)
第三步:在模板里直接使用这个变量
<span>{{ count }}</span>
第四步:修改变量的值
function addOne() {
count.value++
}
完整代码长这样:
<template>
<div>
<span>当前数字:{{ count }}</span>
<button @click="addOne">加1</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
// 创建一个响应式变量count,初始值是0
const count = ref(0)
// 定义一个函数,让count加1
function addOne() {
count.value++
}
</script>
你看,就这么几行代码,一个完整的计数器就做好了。点击按钮,数字会自动增加,页面会自动更新。
2. 小白最困惑的问题:为什么要有.value?
这是所有初学者都会问的问题:" 为什么在 JavaScript 里要写count.value,而在模板里直接写count就行?"
我给你打个比方,你一下子就懂了。
你可以把ref想象成一个透明的盒子。你把值(比如数字 0)放进这个盒子里。
- 当你在模板里使用它的时候,Vue3 会自动帮你打开盒子,拿出里面的值给你看。所以你直接写
{{ count }}就行。 - 当你在 JavaScript 代码里要修改它的时候,你得自己打开盒子,才能修改里面的值。所以你要写
count.value。
就这么简单!.value就是打开盒子的钥匙。
记住这个比喻,你这辈子都不会忘记什么时候要加.value了。
3. ref 还能装对象吗?
答案是:可以,但不推荐。
ref 其实什么都能装,不仅能装简单数据,也能装对象和数组。比如:
const user = ref({
name: '小明',
age: 18
})
但是这样用的话,你修改的时候就得这么写:
user.value.name = '小红'
每次都要加.value,很麻烦。所以对于对象和数组这种复杂数据,我们有更好的工具:reactive。
三、第二个工具:reactive
reactive是专门用来创建响应式的复杂数据的,比如对象和数组。
1. reactive 的基本用法
我们来做一个显示用户信息的例子:
第一步:从 vue 里导入 reactive
import { reactive } from 'vue'
第二步:用 reactive 创建一个响应式对象
const user = reactive({
name: '小明',
age: 18,
gender: '男'
})
第三步:在模板里使用
<div>
<p>姓名:{{ user.name }}</p>
<p>年龄:{{ user.age }}</p>
<p>性别:{{ user.gender }}</p>
</div>
第四步:修改对象的属性
function changeName() {
user.name = '小红'
}
完整代码:
<template>
<div>
<p>姓名:{{ user.name }}</p>
<p>年龄:{{ user.age }}</p>
<p>性别:{{ user.gender }}</p>
<button @click="changeName">改名字</button>
<button @click="addAge">长一岁</button>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const user = reactive({
name: '小明',
age: 18,
gender: '男'
})
function changeName() {
// 直接修改属性,不需要.value!
user.name = '小红'
}
function addAge() {
user.age++
}
</script>
看到了吗?用 reactive 创建的对象,修改属性的时候不需要加.value,直接改就行,就像修改普通的 JavaScript 对象一样。
数组也是一样的用法:
const fruits = reactive(['苹果', '香蕉', '橙子'])
function addFruit() {
fruits.push('草莓') // 直接调用数组方法,完全响应式
}
function changeFirst() {
fruits[0] = '西瓜' // 直接改索引,完全响应式
}
这就是 reactive 的好处:对于对象和数组,用起来和普通的 JavaScript 一模一样,没有任何额外的规则。
四、ref 和 reactive 的区别,一句话总结
讲了这么多,现在我们来总结一下 ref 和 reactive 的区别,非常简单:
简单数据(数字、字符串、布尔值)用 ref,复杂数据(对象、数组)用 reactive。
就这一句话,记住它,99% 的场景你都不会用错。
我再给你列一个简单的对照表,方便你记忆:
| 数据类型 | 推荐使用 | 是否需要.value |
| 数字 | ref | 是 |
| 字符串 | ref | 是 |
| 布尔值 | ref | 是 |
| 对象 | reactive | 否 |
| 数组 | reactive | 否 |
一个非常重要的坑:reactive 不能直接替换整个对象
这是初学者最容易踩的一个坑,我单独拿出来讲。
看下面这个例子:
const user = reactive({
name: '小明',
age: 18
})
// ❌ 错误!这样会丢失响应式!
user = {
name: '小红',
age: 20
}
为什么会这样?因为 reactive 创建的是一个代理对象。你直接把一个普通对象赋值给它,就把原来的代理对象覆盖掉了,Vue3 就再也监控不到它的变化了。
那如果我想替换整个对象怎么办?有两种方法:
方法一:修改每个属性
// ✅ 正确
user.name = '小红'
user.age = 20
方法二:用 ref 来装对象
const user = ref({
name: '小明',
age: 18
})
// ✅ 正确,ref可以直接替换整个值
user.value = {
name: '小红',
age: 20
}
这就是为什么有时候你会看到别人用 ref 来装对象的原因。如果你需要经常替换整个对象,用 ref 会更方便。
五、最佳实践
作为一个初学者,你不用纠结太多复杂的情况。按照下面的规则来写,绝对不会出错:
- 看到数字、字符串、布尔值,直接用
ref - 看到对象、数组,直接用
reactive - 如果你需要经常替换整个对象 / 数组,那就用
ref - 在 JavaScript 里用 ref 的时候,别忘了加
.value - 在模板里用的时候,永远不要加
.value
六、最后说几句
很多人刚接触 Vue3 的时候,会被 ref 和 reactive 搞得头大,觉得怎么这么麻烦。
但其实你用多了就会发现,这两个 API 设计得非常合理。它们把简单数据和复杂数据分开处理,既保证了性能,又保证了使用的便捷性。
而且,一旦你搞懂了这两个 API,Vue3 的大门就向你敞开了。后面所有的知识点,都是建立在这两个基础之上的。
今天这篇我们讲了 Vue3 最核心的两个响应式 API。下一篇我们会讲模板语法,告诉你怎么在页面上显示数据、怎么处理事件、怎么实现条件渲染和列表渲染。
更多推荐
所有评论(0)