feat(watch): 实现watch功能并完善响应式系统
- 新增apiWatch.ts实现watch功能,支持immediate和deep选项 - 扩展ReactiveEffect类添加stop方法用于停止监听 - 导出ReactiveEffect和isReactive函数供外部使用 - 添加ReactiveFlags枚举和IS_REACTIVE标识符 - 在reactive对象上添加__v_isReactive标识 - 导出EMPTY_OBJ常量用于默认参数 - 添加watch功能到Vue入口文件 - 创建watch.html示例验证监听功能正常工作
This commit is contained in:
60
packages/runtime-core/src/apiWatch.ts
Normal file
60
packages/runtime-core/src/apiWatch.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { EMPTY_OBJ, hasChanged } from '@vue/shared'
|
||||
import { isReactive, ReactiveEffect } from '@vue/reactivity'
|
||||
import { queuePreFlushCb } from '@vue/runtime-core'
|
||||
|
||||
export interface WatchOptions<immediate = boolean> {
|
||||
immediate?: immediate
|
||||
deep?: boolean
|
||||
}
|
||||
|
||||
export function watch(source, cb: Function, options?: WatchOptions) {
|
||||
return doWatch(source, cb, options)
|
||||
}
|
||||
|
||||
function doWatch(
|
||||
source,
|
||||
cb: Function,
|
||||
{ immediate, deep }: WatchOptions = EMPTY_OBJ
|
||||
) {
|
||||
let getter: () => any
|
||||
if (isReactive(source)) {
|
||||
getter = () => source
|
||||
deep = true
|
||||
} else {
|
||||
getter = () => {}
|
||||
}
|
||||
//处理deep的状态
|
||||
if (cb && deep) {
|
||||
//todo
|
||||
//浅拷贝的形式--指向同样的内存空间
|
||||
const baseGetter = getter
|
||||
getter = () => baseGetter()
|
||||
}
|
||||
|
||||
let oldValue = {}
|
||||
//每次执行等同于watch被触发一次
|
||||
const job = () => {
|
||||
if (cb) {
|
||||
const newValue = effect.run()
|
||||
if (deep || hasChanged(newValue, oldValue)) {
|
||||
cb(newValue, oldValue)
|
||||
oldValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
//调度器
|
||||
let scheduler = () => queuePreFlushCb(job)
|
||||
const effect = new ReactiveEffect(getter, scheduler)
|
||||
if (cb) {
|
||||
if (immediate) {
|
||||
job()
|
||||
} else {
|
||||
oldValue = effect.run()
|
||||
}
|
||||
} else {
|
||||
effect.run()
|
||||
}
|
||||
return () => {
|
||||
effect.stop()
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export { queuePreFlushCb } from './scheduler'
|
||||
export { watch } from './apiWatch'
|
||||
|
||||
Reference in New Issue
Block a user