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时是nullsource: 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: EffectSchedulerif (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:控制执行时机,实际执行的就是schedulerconst 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_reactivestrigger -> activeEffect -> job
}
// dot language
// graphviz