Vue基础教程(130)组件和组合API之响应式API中的reactive()方法和watchEffect()方法:真香警告!这响应式太丝滑了!

🔥第一章:为什么说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项目里试试这对黄金搭档吧!保证让你发出“真香”的感叹!🚀

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值