前言
重要提示:文章只适合初学者,不适合专家!!!
什么是响应式对象?
在Vue3中,响应式对象就是这种智能温控器。当你修改JavaScript对象的数据时,Vue会自动更新网页上显示的内容,无需手动操作DOM。简单来说:数据变,页面自动跟着变。
创建响应式对象的三种方式
1. reactive() - 用于对象
适合处理对象、数组等复杂数据结构
import { reactive } from 'vue';// 创建一个响应式用户对象
const user = reactive({name: '张三',age: 30,hobbies: ['读书', '游泳']
});// 修改属性 - 自动触发更新
user.age = 31;
user.hobbies.push('登山'); // 数组变化也能检测
2. ref() - 全能选手
适合处理字符串、数字等基本类型,也可以处理对象
import { ref } from 'vue';// 创建一个响应式计数器
const count = ref(0); // 创建响应式字符串
const message = ref('你好Vue3!');// 创建响应式对象(内部会转为reactive)
const settings = ref({theme: 'light',fontSize: 16
});// 修改值时需要通过.value
count.value = 5;
message.value = '欢迎学习响应式';
settings.value.fontSize = 18;
3. toRefs() - 保持响应性的解构
解决reactive对象解构后丢失响应性的问题
import { reactive, toRefs } from 'vue';const user = reactive({name: '李四',age: 25
});// 普通解构会丢失响应性 ❌
// const { name, age } = user;// 使用toRefs保持响应性 ✅
const { name, age } = toRefs(user);// 在脚本中使用要加.value
console.log(name.value); // "李四"
模板和脚本中使用实战
完整组件示例
<template><div class="user-card"><!-- ref对象在模板自动解包,无需.value --><h2>{{ name }}</h2><!-- reactive对象直接使用属性 --><p>年龄: {{ age }} 岁</p><p>状态: {{ isAdult ? "成年人" : "未成年人" }}</p><!-- 使用ref定义的计算属性 --><p>BMI: {{ bmi }}</p><button @click="increaseAge">过生日</button><button @click="changeName">改名</button><input v-model="userInfo.height" type="number" placeholder="输入身高" /></div>
</template><script setup>
import { reactive, ref, computed, toRefs } from "vue";// 使用ref定义基本类型
const name = ref("王小明");// 使用reactive定义对象
const userInfo = reactive({age: 16,height: 175, // 厘米weight: 70, // 公斤
});// 使用toRefs解构,保持响应性
const { age } = toRefs(userInfo);// 计算属性
const bmi = computed(() => {const heightInM = userInfo.height / 100;return (userInfo.weight / (heightInM * heightInM)).toFixed(1);
});// 基于计算属性的状态
const isAdult = computed(() => userInfo.age >= 18);// 修改基本类型的方法
function changeName() {name.value = name.value === "王小明" ? "李小华" : "王小明";
}// 修改响应式对象的方法
function increaseAge() {userInfo.age += 1;userInfo.weight += 1; // 过生日重了1公斤 😄
}
</script><style>
.user-card {border: 1px solid #ccc;padding: 20px;border-radius: 8px;max-width: 300px;
}
button {margin: 5px;
}
</style>
常见疑问解答
1. ref和reactive该用哪个?
场景 | 推荐使用 | 示例 |
---|---|---|
基本类型(数字、字符串) | ref | const count = ref(0) |
对象和数组 | reactive | const user = reactive({...}) |
需要在组件外部传递值 | ref | 模板引用更灵活 |
表单绑定 | ref | v-model="message" |
解构对象属性 | toRefs | const { id } = toRefs(item) |
经验法则:默认使用ref,对象/数组用reactive
2. 为什么我的数据变化没有触发更新?
常见原因:
-
直接解构reactive对象 ❌
错误:const { age } = user
(会丢失响应性)
正确:const { age } = toRefs(user)
✅ -
直接替换reactive对象 ❌
let state = reactive({ count: 0 }); // 错误方式 - 失去响应性 state = { count: 1 };
正确做法:修改属性而不是整个对象 ✅
state.count = 1
-
异步更新数据 ⏳
需要在数据修改后操作DOM?使用nextTick:import { nextTick } from 'vue';count.value++; nextTick(() => {// 此时DOM已经更新console.log(document.getElementById('count').textContent); });
总结:响应式对象核心要点
-
核心概念:数据变 ➔ 视图自动更新
-
创建方式:
reactive()
:用于对象/数组ref()
:用于基本类型、对象引用toRefs()
:安全解构对象属性
-
模板使用:
ref
对象自动解包(不用.value)reactive
对象直接使用属性
-
注意事项:
- 避免直接解构reactive对象
- 修改数组使用push/pop等方法
-
经验法则:
“遇到对象用reactive,其他情况用ref”