vue3: watch和watchEffect

vue3: watch和watchEffect

两者区别
  1. watch:在每次响应式状态发生变化时触发回调函数,是懒执行的:仅在侦听源变化时,才会执行回调。只追踪明确侦听的源。它不会追踪任何在回调中访问到的东西。另外,仅在响应源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。

  2. watchEffect:会立即执行一遍回调函数,如果这时函数产生了副作用,Vue 会自动追踪副作用的依赖关系,自动分析出响应源。watchEffect则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式 property。这更方便,而且代码往往更简洁,但其响应性依赖关系不那么明确。

先看一段代码:

<template>
<div class="home">
  <div>timeTemp: {{timeTemp}}</div>
  <div>number: {{number}}</div>
  <div>number1: {{number1}}</div>
  <div>number2: {{number2}}</div>
  <van-button type="primary" @click="clickAdd">点击增加</van-button>
  <van-button type="primary" @clik="changeTime">点击获取时间戳</van-button>
</div>
</template>

<script setup lang="ts" name="home">
import { watch, watchEffect } from "@vue/runtime-core"

const number = ref(1)
const number1 = ref(0)
const number2 = ref(0)
const timeTemp = ref(0)

const clickAdd = () => {
  number.value ++
}
const changeTime = () => {
  timeTemp.value = Date.now()
}
watch(number,(newVal,oldVal)=>{
  number1.value = number.value * 2
})

watchEffect(()=>{
  number2.value = `${number.value * 3}-${timeTemp.value}` 
})

</script>

初始化时:
在这里插入图片描述

可见,watch在初始化的时候是不会执行回调函数的,所以number1还是0,不是2。而watchEffect初始化时就执行了回调,所以number2是3。

点一下:

在这里插入图片描述

watch和watchEffect都执行了回调,相应的数据已发生改变。

我们点一下【点击获取时间戳】:

在这里插入图片描述

可见watchEffect也执行了回调,即它会在同步执行过程中,自动追踪所有能访问到的响应式 property,这里便是number和timeTemp。同为响应式的number2在watchEffect外改变时时,并不会触发watchEffect的回调。

watch监听多个响应式变量:
watch([number,timeTemp, ()=>obj.count ],()=>{
  console.log(number.value,timeTemp.value)
})
watch监听响应式对象中的某个值改变:

错误示例:

const obj = reactive({ count: 0 })

// 这不起作用,因为你是向 watch() 传入了一个 number
watch(obj.count, (count) => {
  console.log(`count is: ${count}`)
})

正确用法:使用getter 函数,监听obj的count属性改变,只有obj的count改变时才会触发watch回调。

watch(
  () => obj.count,
  (count) => {
    console.log(`count is: ${count}`)
  }
)
watch监听整个响应式对象(深度监听):
const number = reactive({count:1,num:0})

watch(number,()=>{
  console.log(number)
})

此时当count或num改变时就会触发watch回调。这也是一个深度监听,number内部属性改变时都会触发,你也可以显示的增加一个deep选项:

const number = reactive({count:1,num:0})

watch(
    number,
    ()=>{
      console.log(number)
    },
    { deep: true }
)
清除watch

setup()<script setup> 中用同步语句创建的侦听器,会自动绑定到宿主组件实例上,并且会在宿主组件卸载时自动停止。因此,在大多数情况下,你无需关心怎么停止一个侦听器。

如果用异步回调创建一个侦听器,那么它不会绑定到当前组件上,你必须手动停止它,以防内存泄漏。

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

// 它会自动停止
watchEffect(() => {})

// ...这个则不会!
setTimeout(() => {
  watchEffect(() => {})
}, 100)
</script>

要手动停止一个侦听器,请调用 watchwatchEffect 返回的函数:

const unwatch = watchEffect(() => {})

// ...当该侦听器不再需要时
unwatch()

看看react的useEffect

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mosowe

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值