Vue3中watch和watchEffect的区别及使用技巧总结

 更新时间:2026年02月27日 09:16:18   作者:涔溪  
在Vue.js里,watch和watchEffect都用于响应式地追踪数据变化并执行相应操作,不过它们在使用方式、应用场景等方面存在差异,这篇文章主要介绍了Vue3中watch和watchEffect区别及使用技巧的相关资料,需要的朋友可以参考下

详细讲解Vue 3 组合式 API 中watchwatchEffect的核心区别,以及它们的实际使用技巧,以便在开发中根据场景正确选择合适的侦听器。

一、先明确两者的核心定位

在 Vue 3 组合式 API 中,watchwatchEffect都是用于监听响应式数据变化并执行副作用的工具,但设计理念和使用场景有明显区别:

  • watch显式监听指定的响应式数据源,惰性执行(默认),支持访问新旧值,控制力更强。
  • watchEffect隐式监听函数内用到的所有响应式数据源,立即执行(默认),自动追踪依赖,写法更简洁。

二、核心区别对比(表格 + 示例)

对比维度watchwatchEffect
依赖追踪方式显式指定监听源(需明确告诉要监听什么)隐式追踪(自动收集函数内用到的响应式数据)
执行时机默认懒执行(仅当监听源变化时执行)默认立即执行(组件挂载时先执行一次,再监听变化)
新旧值访问支持(回调函数接收新值、旧值参数)不支持(只能访问当前最新值)
监听源类型可监听单个值、多个值、对象属性、计算属性等只能监听函数内直接使用的响应式数据
停止监听返回停止函数,或依赖组件卸载自动停止同左(返回停止函数,组件卸载自动停止)
清除副作用需通过onInvalidate回调(Vue 3.2 + 推荐)同左(回调函数接收onInvalidate参数)

1. 依赖追踪方式对比(最核心区别)

watch:显式指定监听源

必须明确告诉watch要监听哪个 / 哪些响应式数据,未指定的不会被追踪:

<script setup>
import { ref, watch } from 'vue'

const count = ref(0)
const name = ref('Vue')

// 显式监听 count,name 变化不会触发此 watch
watch(count, (newVal, oldVal) => {
  console.log(`count从${oldVal}变成${newVal}`)
})

// 显式监听多个源(数组形式)
watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
  console.log(`count变化:${oldCount}→${newCount},name变化:${oldName}→${newName}`)
})
</script>

watchEffect:隐式追踪依赖

无需指定监听源,函数内用到的所有响应式数据都会被自动追踪:

<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)
const name = ref('Vue')

// 自动追踪 count 和 name(函数内用到了这两个响应式数据)
watchEffect(() => {
  console.log(`当前count:${count.value},当前name:${name.value}`)
})
// 首次执行输出:当前count:0,当前name:Vue(立即执行特性)
// 当count或name变化时,会重新执行
</script>

2. 执行时机对比

watch:默认懒执行

只有监听源发生变化时才会执行,组件挂载时不会主动执行:

<script setup>
import { ref, watch } from 'vue'

const count = ref(0)

// 组件挂载时不会执行,只有 count 变化时才执行
watch(count, (newVal) => {
  console.log(`count变化了:${newVal}`)
})

// 若需要立即执行,需手动设置 immediate: true
watch(count, (newVal) => {
  console.log(`count(立即执行):${newVal}`)
}, { immediate: true }) // 组件挂载时执行一次,之后 count 变化再执行
</script>

watchEffect:默认立即执行

组件挂载时会先执行一次(用于收集依赖),之后依赖变化时再执行:

<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)

// 组件挂载时立即执行一次,之后 count 变化时再执行
watchEffect(() => {
  console.log(`count:${count.value}`)
})
// 输出:count:0(挂载时)→ count:1(当count++时)
</script>

3. 新旧值访问对比

watch:支持访问新旧值

回调函数的第一个参数是新值,第二个参数是旧值(引用类型需注意浅对比):

<script setup>
import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newVal, oldVal) => {
  console.log(`旧值:${oldVal},新值:${newVal}`) // 例如:旧值:0,新值:1
})

// 监听对象(需注意:默认是浅监听,对象内部属性变化需开启 deep: true)
const user = ref({ name: 'Vue', age: 3 })
watch(user, (newUser, oldUser) => {
  console.log('user变化了', newUser, oldUser)
}, { deep: true }) // 深度监听对象内部属性
</script>

watchEffect:不支持访问旧值

只能访问当前最新的响应式数据,无法获取变化前的值:

<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)

watchEffect(() => {
  // 只能拿到当前值,拿不到变化前的旧值
  console.log(`当前count:${count.value}`)
})
</script>

三、使用技巧与场景选择

1. 什么时候用watch?

  • 需要访问新旧值时(如对比变化前后的数据);
  • 需要明确控制监听源(只监听特定数据,避免无关依赖触发);
  • 需要延迟执行(如使用 flush: 'post' 在 DOM 更新后执行);
  • 需要深度监听对象 / 数组且需要精细控制时;
  • 需要懒执行(仅在数据变化时执行,避免初始化开销)。

实用技巧:

  • 监听对象单个属性:用函数返回具体属性(避免深度监听整个对象,提升性能):

    <script setup>
    import { ref, watch } from 'vue'
    
    const user = ref({ name: 'Vue', age: 3 })
    
    // 只监听 user.name,无需深度监听整个对象
    watch(() => user.value.name, (newName) => {
      console.log(`用户名变化:${newName}`)
    })
    </script>
    
  • 延迟执行(DOM 更新后):使用flush: 'post'

    watch(count, () => {
      // 此时DOM已经更新,可以获取更新后的DOM元素
      console.log(document.getElementById('count').innerText)
    }, { flush: 'post' })
    

2. 什么时候用watchEffect?

  • 副作用依赖多个响应式数据,且无需区分哪个变化(自动追踪所有用到的);
  • 需要立即执行副作用(如初始化时请求数据,之后依赖变化重新请求);
  • 不需要访问旧值,只关注当前最新状态;
  • 写法简洁优先(减少代码量)。

实用技巧:

  • 清除副作用(如取消请求、清除定时器):使用onInvalidate 回调(组件卸载或副作用重新执行前触发):

    <script setup>
    import { ref, watchEffect } from 'vue'
    import axios from 'axios'
    
    const id = ref(1)
    
    watchEffect((onInvalidate) => {
      // 发起请求
      const request = axios.get(`/api/data/${id.value}`)
      
      // 清除函数:组件卸载或 id 变化时触发
      onInvalidate(() => {
        request.cancel() // 取消请求
      })
    })
    </script>
    
  • 延迟执行(同 watch):使用flush: 'post'

    watchEffect(() => {
      // DOM更新后执行
      console.log(document.getElementById('count').innerText)
    }, { flush: 'post' })
    

3. 共同技巧:停止监听

watchwatchEffect都返回一个停止函数,调用后会停止监听(组件卸载时会自动停止,无需手动调用):

<script setup>
import { ref, watch, watchEffect } from 'vue'

const count = ref(0)

// watch 停止监听
const stopWatch = watch(count, (newVal) => {
  console.log(`count:${newVal}`)
})

// watchEffect 停止监听
const stopWatchEffect = watchEffect(() => {
  console.log(`count:${count.value}`)
})

// 手动停止监听(如某个条件满足时)
const stopAll = () => {
  stopWatch()
  stopWatchEffect()
}
</script>

总结

核心区别

  1. 依赖追踪watch显式指定源,watchEffect隐式追踪;
  2. 执行时机watch默认懒执行,watchEffect默认立即执行;
  3. 新旧值watch支持访问新旧值,watchEffect不支持。

场景选择

  • 需旧值、明确监听源、精细控制 → 用 watch
  • 多依赖、立即执行、简洁优先 → 用 watchEffect

关键技巧

  1. watch监听对象单个属性时,用函数返回(避免深度监听);
  2. watchEffect需清除副作用时,使用 onInvalidate
  3. 两者都可通过返回的停止函数手动停止监听,组件卸载时自动停止。

到此这篇关于Vue3中watch和watchEffect的区别及使用技巧总结的文章就介绍到这了,更多相关Vue3 watch和watchEffect使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue实现过渡动画Message消息提示组件示例详解

    vue实现过渡动画Message消息提示组件示例详解

    这篇文章主要为大家介绍了vue实现过渡动画Message消息提示组件示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • Vue实现淘宝购物车三级选中功能详解

    Vue实现淘宝购物车三级选中功能详解

    这篇文章主要介绍了通过Vue实现淘宝购物车中三级选中的功能,文中的实现过程讲解详细,对我们学习Vue有一定的帮助,感兴趣的可以了解一下
    2022-01-01
  • 最新Vue过滤器介绍及使用方法

    最新Vue过滤器介绍及使用方法

    过滤器是vue为开发者提供的功能,常用于文本的格式化,过滤器应该被添加在JavaScrip表达式的尾部,由“管道符”进行调用,这篇文章通过案例给大家讲解Vue过滤器介绍及使用方法,需要的朋友参考下吧
    2022-11-11
  • vue如何循环给对象赋值

    vue如何循环给对象赋值

    这篇文章主要介绍了vue如何循环给对象赋值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • Vue学习笔记之计算属性与侦听器用法

    Vue学习笔记之计算属性与侦听器用法

    这篇文章主要介绍了Vue学习笔记之计算属性与侦听器用法,结合实例形式详细分析了vue.js计算属性与侦听器基本功能、原理、使用方法及操作注意事项,需要的朋友可以参考下
    2019-12-12
  • vue弹窗消息组件的使用方法

    vue弹窗消息组件的使用方法

    这篇文章主要为大家详细介绍了vue弹窗消息组件的使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • element UI中el-dialog实现拖拽功能示例代码

    element UI中el-dialog实现拖拽功能示例代码

    我们在开发中常会遇见拖拽的功能,下面这篇文章主要给大家介绍了关于element UI中el-dialog实现拖拽功能的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • Vue 2中ref属性的使用方法及注意事项

    Vue 2中ref属性的使用方法及注意事项

    这篇文章主要给大家介绍了关于Vue 2中ref属性的使用方法及注意事项的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面跟着小编一起来学习学习吧。
    2017-06-06
  • Vue3中watch的使用详解

    Vue3中watch的使用详解

    这篇文章主要介绍了Vue3中watch的详解,主要包括Vue2使用watch及Vue3使用watch的方法,通过多种情况实例代码相结合给大家详细讲解,需要的朋友可以参考下
    2022-11-11
  • vue监听页面上的报错信息

    vue监听页面上的报错信息

    这篇文章主要介绍了vue监听页面上的报错信息,window.onerror和window.addEventListener(‘error‘)的区别,需要的朋友可以参考下
    2023-10-10

最新评论