-
文件目录:packages/reactivity/src/watch.ts
-
源码解读:主要处理逻辑
- 收集要侦听的数据源source,根据不同类型的数据源分别进行处理,赋值给 getter 函数
-
ref类型的值,通过回调函数返回 source.value
-
reactive类型的值,getter = () => reactiveGetter(source),deep为true,则自动设置深度监听
-
array类型的值,遍历数组中的每一项,根据每一项的数据类型返回 getter 处理函数
-
function类型的值,且有回调函数,赋值 getter =() => call()
-
上述类型都不符合,则复制空函数
-
- 核心处理深度监听值的方法:traverse
- 收集要侦听的数据源source,根据不同类型的数据源分别进行处理,赋值给 getter 函数
function watch(source, cb?, options: WatchOptions) {
let getter: () => any;
let forceTrigger = false
if(isRef(source)) {
getter = () => source.value // 这样写,不会立刻触发 ref 的 get value() {} 方法
} else if (isReactive(source)) {
getter = () => reactiveGetter(source)
forceTrigger = true // 侦听源是对象,强制深度监听
} else if (isArray(source)) {
// 侦听多个数据源
getter = () => {
srouce.map(s => {
if (isRef(s)) {
return s.value
} else if (isReactive(s)) {
return reactiveGetter(source)
} else if (isFunction(s)) {
return call ? call(s, WatchErrorCodes.WATCH_GETTER) : s()
} else {
__DEV__ && warnInvalidSource(s)
}
})
}
} else if (isFunction(source)) {
if (cb) {
getter = call
? () => call(source, WatchErrorCodes.WATCH_GETTER)
: (srouce as () => any)
} else {
// no cb -> simple effect
getter = () => {
}
}
} else {
// 空函数
getter = NOOP
}
}
- reactiveGetter
const reactiveGetter = (source) => {
// 深度监听源数据
if (deep) return source
// 对deep:false或浅层反应,只遍历根级属性
if (isShallow(source) || deep === false || deep === 0)
return traverse(source, 1)
// 对于响应对象上的“deep: undefined”,深度遍历所有属性
return traverse(souce)
}
- traverse函数 传递遍历数据对象,结果传递的要遍历的深度(depth),递归处理监听的源数据,触发 get 操作符。收集 watch 依赖
function traverse(value, depth, seen?) {
if (depth <= 0 || !isObject(value) || value[ReactiveFlags.SKIP] ) {
return value
}
seen = seen || new Set()
if (seen.has(value)) {
return value
}
seen.add(value)
// 递归处理监听第几级
// 也是根据判断源数据不同类型,递归调用traverse,做不同处理
// 每递归一次,depth减一
depth--
if (isRef(value)) {
traverse(value.value, depth, seen)
} else if (isArray(value)) {
} else if (isSet(value) || isMap(value)) {
} else if (isPlainObject(value)) {
}
return value
}
- 定义 job 函数
const job = (immediateFirstRun?: boolean) => {
// 如果定义了 立即执行 参数,会执行回调函数
...
// 在侦听操作之前, 执行 effect.stop, 把现有的侦听操作清除
cleanup()
}
- 创建依赖函数,getter 是触发对象 get 的函数;把收集的getter传入构造类中,返回 effect(
响应式核心,收集/更新依赖)
effect = new ReactiveEffect(getter)
- 把job 传入到 effect.scheduler 异步执行的任务队列中,多次触发 get,确保只是执行一次
- 执行
effect.run(),实际上执行 构造函数 ReactiveEffect 中的effect方法
effect.scheduler = scheduler ? () => scheduler(job, false) : job
...
if (cb) {
if (immediate) {
job(true)
} else {
oldValue = effect.run()
}
} else if (scheduler) {
scheduler(job.bind(null, true), true)
} else {
effect.run()
}
run() {
// 没有正在执行的依赖侦听器,则立即执行搜集的 getter 函数(fn 就是开始定义的 getter 函数)
// 否则,标记赋值,清除正在执行的依赖侦听器,执行 getter 函数
if (!(this.flags & EffectFlags.ACTIVE)) {
return this.fn()
}
this.flag |= EffectFlags.RUNNNING
cleanupEffect(this)
prepareDeps(this)
const prevEffect = activeSub
const prevShouldTrack = shouldTrack
activeSub = this
shouldTrack = true
try {
return this.fn()
} finaly {
if (_DEV__ && activeSub !== this) {
warn()
}
cleanupDeps(this)
activeSub = prevEffect
shouldTrack = prevShouldTrack
this.flag &= ~EffectFlags.RUNNING
}
}
- 最后返回 watchHandle 函数,停止侦听。实际上是调用
effect.stop()
const watchHandle = () => {
effect.stop()
if (scope) {
remove(scope.effects, effect)
}
}