vue3.0 源码解析二 :watch 和 computed原理解析

之前的文章详细的介绍了vue3.0 相应式原理,知道了用proxy代替Object.defineProperty 的利与弊,了解了依赖收集和派发更新的大致流程,知道了vue3.0响应式原理,这节我们一起研究vue3.0中的 watch 有那些变化。

一 watch 和 watchEffect

之前我们讲解到,vue3.0取消了渲染watch概念,取而代之的effect副作用钩子,来完成当依赖项更改而促使视图。

 /* 创建一个渲染 effect */
instance.update = effect(function componentEffect() {
   
   
    //...省去的内容后面会讲到
},{
   
    scheduler: queueJob })

接下来我们一起分析 watchwatchEffect

watch 和 watchEffect 使用

watchEffect
export function watchEffect(
  effect: WatchEffect,
  options?: BaseWatchOptions
): StopHandle {
   
   
  return doWatch(effect, null, options)
}

从watchEffect参数有两个,第一个是副作用函数effect,第二个是参数配置项 options ,我们接下来一一解析各参数的用法。

①依赖项监听

import {
   
    reactive, watchEffect } from 'vue'

const state = reactive({
   
   
  count: 0
})
watchEffect(() => {
   
   
   const number = `my age is ${
     
     state.count}`
   console.log(number)
})

watchEffect需要一个应用所需副作用的函数fn。它立即执行函数,并跟踪在执行过程中作为依赖项使用的所有反应状态属性。在这里state中引入的状态将在初始执行后作为此观察程序的依赖项进行跟踪。什么时候状态在将来的某个时间发生改变时,内部函数将再次执行。

我们可以得出结论
1 首先这个watchEffect函数立即执行一次。
2 里面用到的reactive产生的state里面的count会被作为依赖项跟踪,当触发set,依赖项改变,函数再次执行,达到监听的目的。

②清除副作用

当我们在watchEffect 副作用函数中做一些,dom监听或者定时器延时器等操作的时候,组件卸载的时候需要及时清除这些副作用,避免带来一下滞后的影响,我们需要一个好比在react中useEffect钩子的clean清除函数的功能,同样vue3.0也提供了类似的方法。

watchEffect((onInvalidate)=>{
   
   
   const handerClick = ()=>{
   
   } 
   document.addEventListener('click',handerClick)
   onInvalidate(()=>{
   
   
       /*
        执行时机:  在副作用即将重新执行时,如果在setup()或生命周期钩子函数中使用watchEffect, 则在卸载组件时执行此函数。
       */
       document.removeEventListener('click',handerClick)
    })	
})

③停止监听

vue3.0 对于2.0的watch也做了功能上的弥补,我们可以在必要的时候手动操作终止这些监听效果。

自动停止监听:当watchEffect在组件的setup()函数或生命周期钩子被调用时,侦听器会被链接到该组件的生命周期,并在组件卸载时自动停止。

手动停止监听:

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

③异步操作

vue3.0 中watchEffect 并不像 react中 useEffect那样不支持异步 async await 预发糖,对异步操作完全支持。

 watchEffect(async () => {
   
   })

对于watchEffect第二个参数,主要对watchEffect提供独立的配置项。对监听效果作出调试作用。

export interface BaseWatchOptions {
   
   
  flush?: 'pre' | 'post' | 'sync'
  onTrack?: ReactiveEffectOptions['onTrack']
  onTrigger?: ReactiveEffectOptions['onTrigger']
}

flush

从源码中我们可以看出,options 配置参数有三个分别是flush,onTrack和onTrigger
在需要同步或在组件更新之前重新运行watcher效果的情况下,可以使用flush选项传递一个附加的options对象(默认值为“post”)


watchEffect(
  () => {
   
   
  },
  {
   
   
    flush: 'sync' // 同步触发
  }
)

watchEffect(
  () => {
   
   
  },
  {
   
   
    flush: 'pre' // 在组件更新之前触发
  }
)

onTrack和onTrigger

watchEffect(
  () => {
   
   
  },
  {
   
     
    onTrigger(e) {
   
     //当依赖项的变化触发watcher回调时,将调用onTrigger
       console.log('依赖项改变,触发set')
    },
    onTrack(e){
   
    //
       console.log('依赖项被调用,触发get) 
    }
  }
)

如上我们可以得知:

onTrack 当依赖项的变化触发watcher回调时,将调用onTrigger

onTrigger 当state性属性或ref作为依赖项被调用时候,将调用onTrack。

讲完了watchEffect的基本用法,接下来我们看看watch的用法。

watch

watchapi完全等同于2.x this.$watch(以及相应的watch options)。监视需要监视特定的数据源,并在单独的回调函数中应用副作用。默认情况下,它也是惰性的,即只有当被监视的源发生变化时才调用回调。

与watchEffect相比,watch允许我们:

1 懒散地执行副作用

2 更具体地说明什么状态应该触发观察者重新运行;

3 访问被监视状态的先前值和当前值。

// 监听state
const state = reactive({
   
    count: 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值