Vue 3 源码学习实现 watchEffect 方法 All in One
Vue 3 源码学习实现 watchEffect 方法 All in One
cleanup
watchEffect(async (onCleanup) => {
onCleanup(() => {
console.log('clear');
});
console.log(count.value);
})
// 形参 cleanup
watchEffect(async (cleanup) => {
// 实现形参 cleanup , 没有返回值,怎么执行的 ❓
cleanup(() => {
console.log('clear');
});
console.log(count.value);
})
源码
if (isRef(source)) {
getter = () => source.value
forceTrigger = isShallow(source)
} else if (isReactive(source)) {
getter = () => source
deep = true
} else if (isArray(source)) {
isMultiSource = true
forceTrigger = source.some(isReactive)
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.WATCH_GETTER)
} else {
__DEV__ && warnInvalidSource(s)
}
})
} else if (isFunction(source)) {
if (cb) {
// getter with cb
getter = () =>
callWithErrorHandling(source, instance, ErrorCodes.WATCH_GETTER)
} else {
// no cb -> simple effect
getter = () => {
if (instance && instance.isUnmounted) {
return
}
if (cleanup) {
cleanup()
}
return callWithAsyncErrorHandling(
source,
instance,
ErrorCodes.WATCH_CALLBACK,
[onCleanup]
)
}
}
} else {
getter = NOOP
__DEV__ && warnInvalidSource(source)
}
const job: SchedulerJob = () => {
if (!effect.active) {
return
}
if (cb) {
// watch(source, cb)
const newValue = effect.run()
if (
deep ||
forceTrigger ||
(isMultiSource
? (newValue as any[]).some((v, i) =>
hasChanged(v, (oldValue as any[])[i])
)
: hasChanged(newValue, oldValue)) ||
(__COMPAT__ &&
isArray(newValue) &&
isCompatEnabled(DeprecationTypes.WATCH_ARRAY, instance))
) {
// cleanup before running cb again
if (cleanup) {
cleanup()
}
callWithAsyncErrorHandling(cb, instance, ErrorCodes.WATCH_CALLBACK, [
newValue,
// pass undefined as the old value when it's changed for the first time
oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,
onCleanup
])
oldValue = newValue
}
} else {
// watchEffect
effect.run()
}
}
https://github.com/vuejs/core/blob/main/packages/runtime-core/src/apiWatch.ts#L44
https://github.com/vuejs/core/blob/main/packages/runtime-core/src/apiWatch.ts#L240
https://github.com/vuejs/core/blob/main/packages/runtime-core/src/apiWatch.ts#L320
demo
💩 WTF, 为什么 cleanup 参数不需要定义,怎么传递的呀 ?
/*
const cleanup = () => {
console.log('clear');
}
const onCleanup = () => {
console.log('clear');
}
*/
// 立即执行一次
//
💩 WTF, 为什么 cleanup 参数不需要定义,怎么传递的呀 ?
watchEffect(async (cleanup) => {
// 实现形参, 没有返回值 ?
cleanup(() => {
console.log('clear');
});
console.log(count.value);
})
Vue 3 源码学习实现 watchEffect 方法
// ???
refs
https://vuejs.org/api/reactivity-core.html#watcheffect
https://www.thisdot.co/blog/vue-3-composition-api-watch-and-watcheffect
©xgqfrms 2012-2020
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/16094969.html
未经授权禁止转载,违者必究!