🔥第一章:为什么说reactive()是Vue 3的“变形金刚”?
1.1 从前,有个叫Options API的“老古董”
在Vue 2时代,我们写组件得像填表格一样,把数据塞进data(),方法塞进methods:
export default {
data() {
return {
user: { name: '小明', age: 18 },
score: 100
}
},
methods: {
changeAge() {
this.user.age = 20 // 响应式更新,但嵌套对象得用this.$set
}
}
}
如果想给user加个新属性gender,还得祭出this.$set(this.user, 'gender', '男'),不然视图根本不更新!更别提遇到复杂嵌套对象时,代码写得像在解迷宫🧩。
1.2 reactive():一键开启“全员响应式”
Vue 3的Composition API来了!reactive()就像个魔法阵,把普通对象丢进去,瞬间变成响应式超人:
import { reactive } from 'vue'
const state = reactive({
user: { name: '小明', hobbies: ['干饭', '摸鱼'] },
score: 100
})
// 直接改!不用$set!
state.user.gender = '男' // 视图自动更新!
state.user.hobbies.push('写Vue') // 数组也能跟踪!
原理揭秘:reactive()用了Proxy代理对象,任何属性读写都被拦截。当你state.user.age = 20,Vue在背后悄悄记录:“啊,这个age被改了,快通知视图!”
1.3 实战:用reactive()搞个外卖订单系统
假设我们在写一个外卖App,订单数据长这样:
const order = reactive({
items: [
{ name: '奶茶', price: 15, count: 2 },
{ name: '炸鸡', price: 30, count: 1 }
],
discount: 0.9,
address: { city: '北京', street: '朝阳区' }
})
// 加杯奶茶?
order.items.push({ name: '珍珠奶茶', price: 18, count: 1 })
// 改地址?直接莽!
order.address.street = '海淀区'
// 计算总价(用computed,后面会讲)
const total = order.items.reduce((sum, item) =>
sum + item.price * item.count, 0) * order.discount
看,不用任何辅助方法,直接操作对象就行!但这有个坑:如果给整个对象重新赋值(order = { ... }),响应式会失效!所以记得只修改属性,别替换整个对象。
🎯第二章:watchEffect()——比狗仔队还敬业的“监视者”
2.1 曾经的watch:得明确指定监视目标
Vue 2的watch得像侦探一样明确目标:
watch: {
'user.age'(newVal, oldVal) {
console.log(`年龄从${oldVal}变到${newVal}啦!`)
}
}
如果依赖多个数据?得写一堆监视项,代码瞬间变臃肿。
2.2 watchEffect():自动追踪,智能触发
watchEffect()就像在你代码里装了雷达,凡是它函数里用到的响应式数据,全自动监视!
import { watchEffect } from 'vue'
// 只要order.items或order.discount一变,立即执行!
watchEffect(() => {
const total = order.items.reduce((sum, item) =>
sum + item.price * item.count, 0) * order.discount
console.log(`总价更新:${total}元`)
})
// 修改数据,触发watchEffect
order.items[0].count = 3 // 输出:总价更新:XXX元
order.discount = 0.8 // 再次触发!
更强大的是:它还能自动清理副作用!比如在副作用里设定时器,下次执行前会自动清除之前的。
2.3 实战:游戏血条监控器
假设我们在开发游戏,玩家血量和状态需要实时监控:
const player = reactive({ hp: 100, status: 'healthy' })
// 血条低于20%自动报警
watchEffect((onInvalidate) => {
if (player.hp < 20) {
console.log('警告!残血!快补血!')
// 自动清理示例:5秒后清除警告
const timer = setTimeout(() => {
console.log('警告已清除')
}, 5000)
onInvalidate(() => {
clearTimeout(timer) // 下次执行前或组件卸载时自动调用
})
}
})
// 测试
player.hp = 15 // 触发警告
player.hp = 50 // 不触发(但定时器还在)
player.hp = 10 // 再次触发,同时自动清除了上一个定时器
🚀第三章:reactive() + watchEffect() = 响应式黄金搭档
3.1 组合使用:智能表单验证
我们来做个实时表单验证:
const form = reactive({
email: '',
password: '',
errors: {}
})
// 自动验证,任何一个字段变化都检查
watchEffect(() => {
const errors = {}
if (!form.email.includes('@')) {
errors.email = '邮箱格式不对啦!'
}
if (form.password.length < 6) {
errors.password = '密码太短,不够安全!'
}
form.errors = errors
})
// 在模板中直接显示错误信息
// <div v-if="form.errors.email">{{ form.errors.email }}</div>
3.2 进阶技巧:用toRefs解构reactive
直接从reactive解构会丢失响应式:
// 错误示范
const { user, score } = state // user和score不再是响应式的!
// 正确姿势
import { toRefs } from 'vue'
const { user, score } = toRefs(state) // 现在它们保持响应式
user.value.age = 25 // 记得用.value!
⚠️第四章:避坑指南——这些雷我都帮你踩过了
4.1 reactive()的局限性
- 只适用于对象:对基本类型(string、number)请用
ref() - 不能直接替换:
state = newObject会破坏响应式,应该用Object.assign(state, newObject) - 注意循环引用:深Proxy可能遇到循环引用问题
4.2 watchEffect()使用技巧
- 控制执行时机:默认立即执行,如果想跳过首次,可以用
{ flush: 'post' } - 停止监视:获取返回的stop函数即可
const stop = watchEffect(() => { ... })
stop() // 停止监视
- 避免无限循环:如果在watchEffect里修改依赖的数据,可能造成死循环
🌟第五章:真实场景——用这俩API重构外卖应用
完整示例:一个带自动计算和验证的外卖订单组件
<template>
<div>
<div v-for="(item, index) in order.items" :key="index">
{{ item.name }} - ¥{{ item.price }} ×
<button @click="item.count--">-</button>
{{ item.count }}
<button @click="item.count++">+</button>
</div>
<p>总价:¥{{ total }}</p>
<p v-if="errors.discount" class="error">{{ errors.discount }}</p>
折扣:<input v-model="order.discount" type="number">
<p>配送地址:{{ order.address.city }}{{ order.address.street }}</p>
</div>
</template>
<script setup>
import { reactive, watchEffect, computed } from 'vue'
const order = reactive({
items: [
{ name: '奶茶', price: 15, count: 2 },
{ name: '炸鸡', price: 30, count: 1 }
],
discount: 0.9,
address: { city: '北京', street: '朝阳区' }
})
const errors = reactive({})
// 自动验证折扣
watchEffect(() => {
if (order.discount > 1 || order.discount < 0) {
errors.discount = '折扣必须在0-1之间!'
} else {
errors.discount = ''
}
})
// 计算总价
const total = computed(() => {
return order.items.reduce((sum, item) =>
sum + item.price * item.count, 0) * order.discount
})
</script>
🎉结语:拥抱Composition API的新时代
reactive()和watchEffect()就像Vue 3送给我们的瑞士军刀——灵活、强大、智能。它们让响应式编程从“必须按我的规矩来”变成了“你怎么方便怎么来”。
记住这个组合拳:
- 复杂数据用
reactive()——对象、数组交给它 - 副作用用
watchEffect()——自动追踪,省心省力 - 解构用
toRefs()——保持响应式不掉线
现在就去你的Vue 3项目里试试这对黄金搭档吧!保证让你发出“真香”的感叹!🚀

被折叠的 条评论
为什么被折叠?



