-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpure.js
103 lines (83 loc) · 2.15 KB
/
pure.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// 实现响应式
// 当 b 依赖 a 时,a 变化时,b 自动执行
// 条件:1. b 依赖 a => 这个是代码实现的前置条件
// 条件:2. a 变化 => 这个是代码实现的前置条件
// 预期:自动执行 b => 这个是后面代码要实现的目的
// import { reactive, watchEffect } from "./vue-demo"
// 用代码做说明
let a = {
num: 0
}
const b = function () {
// 条件 1. b 依赖 a
console.log('=== func b ===', a.num)
}
// // 条件 2. a 发生变化了
// a.num += 1
// 预期:自动出现 === func b === 1
// ========================
// 下面是 Vue api 调用方式,我们要仿照 vue 设计出相同的调用方式
// a = reactive({
// num: 0
// })
// watchEffect(b)
// a.num += 1
// => 代码需要暴露两个方法
// 1. reactive:负责把原始对象包裹成响应式对象
// 2. watchEffect 这是个包裹函数,要做的第一件事执行原有函数,保持原有意义,第二件事,把当前的这个函数指向一个 activeEffect 全局变量, 已供收集
const targetMap = new WeakMap()
// 需要把下方 activeEffect 收集到上方的 targetMap
let activeEffect
function reactive (obj) {
const proxy = new Proxy(obj, {
get: function (target, key) {
// 追踪
track(target, key)
return Reflect.get(target, key)
},
set: function (target, key, val) {
const observed = Reflect.set(target, key, val)
// 派发
trigger(target, key)
return observed
}
})
return proxy
}
function track (target, key) {
if (!activeEffect) {
return
}
let desMap = new Map()
let effects = new Set()
// console.log(activeEffect, '333')
effects.add(activeEffect)
desMap.set(key, effects)
targetMap.set(target, desMap)
}
function trigger (target, key) {
const desMap = targetMap.get(target)
const effects = desMap.get(key)
effects.forEach(effect => {
effect()
})
}
function watchEffect (fn) {
const wrapped = function () {
try {
activeEffect = fn
return fn()
}
finally {
activeEffect = undefined
}
}
wrapped()
return wrapped
}
// 下面是用户代码
a = reactive({
num: 0
})
watchEffect(b)
a.num += 1