找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4411

积分

0

好友

592

主题
发表于 5 小时前 | 查看: 3| 回复: 0

在 Vue 3 的响应式系统中,watchwatchEffect 是两个至关重要的工具,用于观察和响应数据的变化。但你是否清楚它们各自的适用场景?什么时候该用 watch,什么时候又该用 watchEffect 呢?这篇指南将通过具体的代码示例,帮你理清两者的核心区别与最佳实践。

1. watch 的详细用法

watch API 提供了一种显式、可配置的方式来侦听一个或多个响应式数据源的变化。

监听 ref 定义的响应式数据

对于 ref 创建的响应式数据,直接将其作为 watch 的第一个参数即可。

<template>
  <div>
    <div>值:{{count}}</div>
    <button @click="add">改变值</button>
  </div>
</template>

<script>
import { ref, watch } from 'vue';
export default {
  setup(){
    const count = ref(0);
    const add = () => {
      count.value ++
    };
    watch(count,(newVal,oldVal) => {
      console.log('值改变了',newVal,oldVal)
    })
    return {
      count,
      add,
    }
  }
}
</script>

监听 reactive 定义的响应式数据

当监听整个 reactive 对象时,watch 会默认启用深度侦听。

<template>
  <div>
    <div>{{obj.name}}</div>
    <div>{{obj.age}}</div>
    <button @click="changeName">改变值</button>
  </div>
</template>

<script>
import { reactive, watch } from 'vue';
export default {
  setup(){
    const obj = reactive({
      name:'zs',
      age:14
    });
    const changeName = () => {
      obj.name = 'ls';
    };
    watch(obj,(newVal,oldVal) => {
      console.log('值改变了',newVal,oldVal)
    })
    return {
      obj,
      changeName,
    }
  }
}
</script>

监听多个响应式数据

通过将多个数据源放入数组,可以同时侦听它们的变化。

<template>
  <div>
    <div>{{obj.name}}</div>
    <div>{{obj.age}}</div>
    <div>{{count}}</div>
    <button @click="changeName">改变值</button>
  </div>
</template>

<script>
import { reactive, ref, watch } from 'vue';
export default {
  setup(){
    const count = ref(0);
    const obj = reactive({
      name:'zs',
      age:14
    });
    const changeName = () => {
      obj.name = 'ls';
    };
    watch([count,obj],() => {
      console.log('监听的多个数据改变了')
    })
    return {
      obj,
      count,
      changeName,
    }
  }
}
</script>

监听对象中某个属性的变化

有时你只需要关注对象内的一个特定属性,这时可以使用 getter 函数作为数据源。

<template>
  <div>
    <div>{{obj.name}}</div>
    <div>{{obj.age}}</div>
    <button @click="changeName">改变值</button>
  </div>
</template>

<script>
import { reactive, watch } from 'vue';
export default {
  setup(){
    const obj = reactive({
      name:'zs',
      age:14
    });
    const changeName = () => {
      obj.name = 'ls';
    };
    watch(() => obj.name,() => {
      console.log('监听的obj.name改变了')
    })
    return {
      obj,
      changeName,
    }
  }
}
</script>

深度监听 (deep) 和默认执行 (immediate)

通过第三个参数配置对象,你可以控制 watch 的深度侦听行为以及是否在初始化时立即执行回调。

<template>
  <div>
    <div>{{obj.brand.name}}</div>
    <button @click="changeBrandName">改变值</button>
  </div>
</template>

<script>
import { reactive, watch } from 'vue';
export default {
  setup(){
    const obj = reactive({
      name:'zs',
      age:14,
      brand:{
        id:1,
        name:'宝马'
      }
    });
    const changeBrandName = () => {
      obj.brand.name = '奔驰';
    };
    watch(() => obj.brand,() => {
      console.log('监听的obj.brand.name改变了')
    },{
      deep:true,
      immediate:true,
    })
    return {
      obj,
      changeBrandName,
    }
  }
}
</script>

2. watchEffect 的用法

watchEffect 是另一种响应式副作用的工具,它的心智模型与 watch 有所不同。

基本用法

watchEffect 会自动追踪其回调函数内部所访问的所有响应式依赖,并在它们发生变化时立即重新执行。

<template>
  <div>
    <input type="text" v-model="obj.name">
  </div>
</template>

<script>
import { reactive, watchEffect } from 'vue';
export default {
  setup(){
    let obj = reactive({
      name:'zs'
    });
    watchEffect(() => {
      console.log('name:',obj.name)
    })

    return {
      obj
    }
  }
}
</script>

停止侦听

watchEffect 会返回一个停止函数,调用它可以手动停止侦听。

<template>
  <div>
    <input type="text" v-model="obj.name">
    <button @click="stopWatchEffect">停止监听</button>
  </div>
</template>

<script>
import { reactive, watchEffect } from 'vue';
export default {
  setup(){
    let obj = reactive({
      name:'zs'
    });
    const stop = watchEffect(() => {
      console.log('name:',obj.name)
    })
    const stopWatchEffect = () => {
      console.log('停止监听')
      stop();
    }

    return {
      obj,
      stopWatchEffect,
    }
  }
}
</script>

3. 核心总结与选择指南

了解了两者的具体用法后,我们再来系统性地对比一下它们的核心特点,这有助于你在实际开发中做出正确的选择。

watch 的核心特点

  • 有惰性:默认情况下,不会在侦听器创建时立即执行回调,只有数据源变化后才执行。
  • 更加具体:需要显式指定要侦听的单个或多个数据源。
  • 可访问变化前后的值:回调函数会接收 newValueoldValue 作为参数。
  • 高度可配置
    • immediate:控制是否立即执行。
    • deep:控制是否进行深度侦听。

watchEffect 的核心特点

  • 非惰性:创建后会立即执行一次,以收集依赖。
  • 更加抽象和简洁:自动追踪回调函数内所有被使用的响应式依赖,无需手动声明。
  • 不可直接访问旧值:回调函数中没有旧值参数,只能获取到当前的最新值。
  • 自动停止:当组件卸载时,侦听器会自动停止。

如何选择?

  • 使用 watch 的场景:当你需要明确知道是哪个值发生了变化,并且需要用到变化前后的值进行比较或逻辑处理时;或者当你需要惰性执行、深度监听等精细化控制时。
  • 使用 watchEffect 的场景:当你需要执行的副作用逻辑依赖于多个响应式状态,并且你更关心逻辑执行(基于当前最新值)而非具体哪个值变化时。它能简化代码,自动管理依赖关系。

watch API 参数详解

watch 的函数签名非常清晰:watch(source, callback, options)

第一个参数(数据源 source 可以是:

  • 一个返回值的 getter 函数
  • 一个 ref
  • 一个 reactive 对象
  • 以上类型组成的数组

第二个参数(回调函数 callback

(newValue, oldValue, onCleanup) => {
  // 副作用清理
  onCleanup(() => { /* 清理逻辑 */ });
}

第三个参数(配置选项 options

interface WatchOptions {
  immediate?: boolean // 默认 false
  deep?: boolean // 默认 false
  flush?: 'pre' | 'post' | 'sync' // 默认 'pre'
  onTrack?: (event: DebuggerEvent) => void
  onTrigger?: (event: DebuggerEvent) => void
  once?: boolean // Vue 3.4+ 默认 false
}

掌握 watchwatchEffect 的差异,能让你在构建 Vue.js 应用时更加得心应手,根据不同的业务场景选择最合适的响应式侦听方案。希望这篇指南能帮助你更深入地理解 Vue 3 的响应式副作用系统。如果你想与其他开发者交流更多前端框架的实战心得,欢迎来云栈社区分享你的见解。




上一篇:前端转全栈:从零到一搭建与部署 Node.js 服务器实战指南
下一篇:Claude Code对比Codex 2026:AI编程工具基准测试与Agent架构深度解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-29 06:27 , Processed in 0.570890 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表