-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreactive.ts
131 lines (120 loc) · 2.79 KB
/
reactive.ts
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// 第一版
// let activeEffect: Function | undefined
// class Dep {
// subscript: Set<Function> = new Set()
// depend() {
// if (activeEffect) {
// this.subscript.add(activeEffect)
// }
// }
// notify() {
// this.subscript.forEach((effect) => effect())
// }
// }
// function watchEffect(effect) {
// activeEffect = effect
// effect()
// }
// let dep = new Dep()
// let actualCount = 0
// const state = {
// get count() {
// dep.depend()
// return actualCount
// },
// set count(newVal) {
// actualCount = newVal
// dep.notify()
// }
// }
//第二版
// let activeEffect: Function | undefined
// class Dep {
// subscribers: Set<Function> = new Set()
// depend() {
// this.subscribers.add(activeEffect)
// }
// notify() {
// this.subscribers.forEach(effect => effect())
// }
// }
// function watchEffect(effect) {
// activeEffect = effect
// effect()
// }
// function reactive(raw: object) {
// Object.keys(raw).forEach(key => {
// let dep = new Dep()
// Object.defineProperty(raw, key, {
// get() {
// dep.depend()
// return raw[key]
// },
// set(newVal) {
// raw[key] = newVal
// dep.notify()
// }
// })
// })
// }
//第三版
let activeEffect: Function | undefined
class Dep {
subscribers: Set<Function> = new Set()
_value: any
constructor(value: any) {
this._value = value
}
get value() {
this.depend()
return this._value
}
set value(newVal) {
this._value = newVal
this.notify()
}
depend() {
if (activeEffect) {
this.subscribers.add(activeEffect)
}
}
notify() {
this.subscribers.forEach(effect => effect())
}
}
function watchEffect(effect: Function) {
activeEffect = effect
effect()
activeEffect = null
}
let reactiveHandlers: ProxyHandler<any> = {
get(target, key) {
const value = getDep(target, key).value
if (value && typeof value === 'object') {
return reactive(value)
} else {
return value
}
},
set (target: any, key: any, value: any) {
getDep(target, key).value = value
return true
}
}
const targetToHashMap = new WeakMap()
function getDep(target, key) {
let depMap = targetToHashMap.get(target)
if (!depMap) {
depMap = new Map()
targetToHashMap.set(target, depMap)
}
let dep = depMap.get(key)
if (!dep) {
dep = new Dep(target[key])
depMap.set(key, dep)
}
return dep
}
function reactive(raw: object) {
return new Proxy(raw, reactiveHandlers)
}