https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/apiWatch.ts
目录
Watch
@/packages/runtime-core/src/apiWatch.ts
watch.dot
https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/apiWatch.ts
Watch
@/packages/runtime-core/src/apiWatch.ts
watch和watchEffect都是在调用doWatch函数,所以文核心就是doWatch函数
export function watchEffect(
    effect: WatchEffect,
    options?: WatchOptionsBase
){
  return doWatch(effect, null, options)  
}
export function watchPostEffect(
    effect: WatchEffect,
    options?: DebuggerOptions
){
    options.plush = 'post'
    return doWatch(effect, null, options)  
}
export function watchSyncEffect(
    effect: WatchEffect,
    options?: DebuggerOptions
){
    options.plush = 'sync'
    return doWatch(effect, null, options)  
}
// 上面几个函数都指向doWatch()
// 对watch函数进行重载,4次
export function watch<
    T extends MultiWatchSources,
    Immediate extends Readonly<boolean> = false
>(
    sources:[...T],
    cb: WatchCallback<MapSources<T,false>,MapSources<T,Immediate>>,
    options?: WatchOptions<Immediate>
): WatchStopHandle
// ...
export function watch<
    T = any,
    Immediate extends Readonly<boolean> = false
>(
    sources: T | WatchSource<T>,
    cb: any,
    options?: WatchOptions<Immediate>
): WatchStopHandle {
    return doWatch(source as any, cb, options)
}
// 核心函数 doWatch
function doWatch(
    // source:
    // WatchSource是个ref
    // WatchEffect是个副作用
    // cb:
    // watch独有的,watchEffect时是null
    source: WatchSource | WatchSource[] | WatchEffect | object,
     cb: WatchCallback | null,
     { immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ
): WatchStopHandle {
    let getter:()=> any // 获取值
    // 会有不同的回调
    if(isRef(source)) {
        getter = () => source.value    
    } else if (isReactive(spurce)) {
        getter = () => source    
    } else if (isArray(source)) {
        getter = () => 
        source.map(s => {
            if(isRef(s)) {
                return s.value            
            } else if (isReactive(s)) {
                return traverse(s)            
            } else if (isFunction(s)) {
                // 报错
                return callWithErrorHandling(s, instance, ErrorCodes.WARCH_GETTER)            
            } else {
                __DEV__ && warnInvalidSource(s)  // 报错      
            }
        })    
    } else if (isFunction(source)) {
        if(cb) {
            // watch        
        } else {
            // watchEffect        
        } 
    }
    
    // ...
    // job是effect具体要做的事情
     const job: SchedulerJob = () => {
       if(cb) {
          // watch(source, cb)
          const newValue = effect.run() // 执行一下,拿到新的值 ,基于getter拿到的effect         
          // 一些验证条件,通过之后会执行cb
          // if...
          // 	if.... hasChanged(newValue, oldValue) // 发送变化才执行
          			callWithAsyncErrorHandling(cb, ...)
        }   
           
     }
     let scheduler: EffectScheduler
     if (flush === 'sync') {
        scheduler = job as any // 直接调用调度程序函数
     } else if (flush === 'post') {
         // 放队列里,一项一项执行
         scheduler = () => queuePostRenderEffect(job, instance && instance.suspense)
     } else {
         // default: 'pre' //也放到一个队列里
         scheduler = () => {
             if (!instance || instance.isMounted) {
                 queuePreFlushCb(job)             
             } else {
                 // 使用“pre”选项,第一次呼叫必须在
                 // 组件已安装,因此可以同步调用它。
                 job()             
             }        
         }     
     }
     // new 一个 effect;scheduler:控制执行时机,实际执行的就是scheduler
     const effect = new ReactiveEffect(getter, scheduler)
}watch.dot
digraph {
  watchEffect -> doWatch;
  watch -> doWatch;
  doWatch -> reactiveWrapper -> initialGet;
  activeEffect[color=green]
  reactiveWrapper -> activeEffect[dir=none]
  initialGet -> trackAll_refs_reactives
  trigger -> activeEffect -> job
}
// dot language
// graphviz 







![[STC32F12K54入门第三步]USART1+Modbus RTU从机](https://img-blog.csdnimg.cn/9264432e90cd4852ab11eff138936dab.png)


![[MAUI]用纯C#代码写两个漂亮的时钟](https://img-blog.csdnimg.cn/b4595c759c9842859411df3a4516049d.gif)








