Vue3中watch和watchEffect的用法

本文详细介绍了Vue中`watch`和`watchEffect`的用法,包括监听ref、getter函数、响应式对象的变化,以及它们的懒执行特性、深度监听和生命周期管理。
// watch和watchEffect
const x = ref(0)
const y = ref(0)
// 监听ref
watch(x, (val) => {
  console.log('监听x变化=' + val)
})
// 监听 getter 函数
watch(
  () => x.value + y.value,
  (sum) => {
    console.log('监听x和y变化后计算和=' + sum)
  }
)
// 监听多个来源组成的数组
watch([x, y], ([newX, newY]) => {
  console.log('监听x变化=' + newX)
  console.log('监听y变化=' + newY)
})

setTimeout(() => {
  x.value = 5
  y.value = 6
}, 2000)
// 不能直接侦听响应式对象的属性值,相当于传了一个number值,无法监听
const obj = reactive({ count: 10 })
watch(obj.count, (c) => {
  console.log('普通监听count变化了=' + c)
})
// 需要监听响应式对象的属性值,就需要监听getter函数
watch(
  () => obj.count,
  (c) => {
    console.log('监听getter函数count变化了=' + c)
  }
)
// 给watch传入一个响应式的对象,会隐式的创建一个深层监听器,会监听这个对象所有的属性变化,

watch(obj, (o) => {
  console.log('深层监听器count变化了=' + o.count)
})
// 如果要显式的使用深层监听器,需要传入{deep:true}的配置项,监听响应式对象,如果对象嵌套复杂,会影响性能消耗
watch(
  () => obj,
  (o) => {
    console.log('显式深层监听器count变化了=' + o.count)
  },
  { deep: true }
)
obj.count = 9
// watch()是懒执行的:仅在侦听源变化时,才会执行回调
// ================================================================
// 如果想创建侦听器后立即执行监听,就需要使用watchEffect,它会在创建时自动追踪访问到的属性变化

const effect = reactive({ name: 'zs', age: 18 })
// 默认会监听打印zs,name变化后会再次打印李素,监听会掉中不要使用异步,这会让默认监听变的无效
watchEffect(() => {
  console.log('创建后自动监听属性name=' + effect.name)
})
effect.name = '李素'
// 默认情况下,创建的监听器都会在vue更新页面前调用。这就意味着你在侦听器中访问dom是更新前的状态,要访问更新后的dom,就需要显式的使用配置flush:'post'或者watchPostEffect
watch(
  () => obj.count,
  (c) => {
    console.log('watch页面更新后的监听' + c)
  },
  { flush: 'post' }
)
watchEffect(
  () => {
    console.log('watchEffect页面更新后的监听' + obj.count)
  },
  { flush: 'post' }
)
watchPostEffect(() => {
  console.log('watchPostEffect页面更新后的监听' + obj.count)
})
obj.count = 100
// 同步创建的侦听器会自动绑定到宿主实例上,宿主销毁侦听器自动结束。
// 异步创建的侦听器不会自动绑定到宿主的实例上,需要手动结束
let unwatch = null
setTimeout(() => {
  unwatch = watch(
    () => obj,
    (o) => {
      console.log('异步侦听器器' + o.count)
    }
  )
}, 1000)
onBeforeUnmount(() => {
  if (unwatch != null) unwatch()
})
setTimeout(() => {
  obj.count = 300
}, 3000)

### Vue3 中 `watch` `watchEffect` 的使用场景及区别 #### 1. 基本概念 `watch` `watchEffect` 都是 Vue 3 提供的响应式工具,用于监听数据变化并触发相应的副作用逻辑。然而,两者的实现机制适用场景存在显著差异。 #### 2. 工作原理对比 - **`watchEffect`**: 自动收集依赖项,并在这些依赖项发生改变时重新运行回调函数[^2]。它会在定义时立即执行一次,以便捕获初始状态下的依赖关系。 - **`watch`**: 明确指定需要监听的数据源(可以是一个或多个),当这些数据源发生变化时才触发回调函数[^1]。默认情况下不会在组件挂载时立即执行。 #### 3. 使用语法对比 以下是两者的基本用法: ##### `watchEffect` ```javascript import { ref, watchEffect } from &#39;vue&#39;; const count = ref(0); const doubledCount = ref(0); watchEffect(() => { doubledCount.value = count.value * 2; }); ``` 此代码片段展示了如何利用 `watchEffect` 动态计算变量 `doubledCount` 的值[^2]。 ##### `watch` ```javascript import { ref, watch } from &#39;vue&#39;; const user = ref({ name: &#39;Alice&#39;, age: 25 }); const userNameHistory = []; watch( () => user.value.name, (newName, oldName) => { console.log(`User&#39;s name changed from ${oldName} to ${newName}`); userNameHistory.push(newName); } ); ``` 这段代码说明了如何通过 `watch` 方法监控特定属性的变化,并记录历史名称[^1]。 #### 4. 初始化行为 - **`watchEffect`**: 定义后会立刻执行一次回调函数,从而完成初次依赖跟踪[^2]。 - **`watch`**: 默认不支持首次执行;如果希望在初始化阶段也调用回调,则需额外配置选项 `{ immediate: true }`[^3]。 #### 5. 性能考量 由于 `watchEffect` 不允许开发者手动控制其观察范围,因此可能会引入不必要的性能开销——即使某些依赖并未实际参与业务逻辑运算也会被纳入监测体系之中。相比之下,`watch` 更加灵活可控,能够精确限定关注目标,减少无谓重算次数。 #### 6. 应用实例分析 假设有一个需求:每当输入框中的数值发生变化时都需要同步调整另一个字段的内容。此时可以选择如下方案之一: - 如果仅关心最终效果呈现而无需区分具体变动细节的话,那么采用简洁高效的 `watchEffect` 将更为合适; - 若还需要进一步处理比如验证有效性或者保存变更日志之类的附加操作,则推荐运用功能全面但相对复杂的 `watch` 来达成目的。 --- ### 示例代码对比 #### 使用 `watchEffect` ```javascript <script> export default { data() { return { a: 1, b: 2, sum: null }; }, mounted() { this.sum = this.a + this.b; watchEffect(() => { this.sum = this.a + this.b; }); } }; </script> ``` #### 使用 `watch` ```javascript <script> export default { data() { return { a: 1, b: 2, sum: null }; }, mounted() { this.sum = this.a + this.b; watch([() => this.a, () => this.b], ([newA, newB]) => { this.sum = newA + newB; }, { immediate: true }); } }; </script> ``` 以上两个例子分别演示了基于不同 API 实现相同功能的方式方法[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值