-
Notifications
You must be signed in to change notification settings - Fork 0
/
observer.js
73 lines (63 loc) · 2.22 KB
/
observer.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
/**
* obsever.js
*
* 功能
* - 把$data中的属性转换成响应式数据
* - 如果$data中的某个属性也是对象,把该属性也转换成响应式数据
* - 数据变化的时候,发送通知
*
* 方法:
* - walk(data) -遍历data属性,调用defineReactive将数据转化如getter/setter
* - defineReactive(data,key,value) - 将数据转化成getter/setter
*
*/
class Observer {
constructor(data) {
this.walk(data)
}
// 1.遍历data转为响应式
walk(data) {
// 如果data为空或者data不是对象 return
if (!data || typeof data !== "object") {
return
}
// 遍历data,变成响应式
Object.keys(data).forEach((key) => {
this.defineReactive(data, key, data[key])
})
}
// 2.将data中的属性转为getter/setter
defineReactive(data, key, value) {
// 检测属性是否是对象,是对象的话,继续将对象转化为响应式的
this.walk(value)
// 保存一下this
const that = this
// 创建Dep对象,给每个data添加一个观察者
let dep = new Dep()
Object.defineProperty(data, key, {
// 可枚举(可遍历)
enumerable: true,
// 可配置(可以使用delete删除,可以通过defineProperty重新定义)
configurable: true,
// 获取值的时候执行
get() {
// 在这里添加观察者对象 Dep.target 表示观察者
Dep.target && dep.addSub(Dep.target)
return value
},
// 设置新值
set(newValue) {
// 若新值等于旧值则返回
if (newValue == value) {
return
}
// 如新值不等于旧值则赋值 此处形成了闭包,延长了value的作用域
value = newValue
// 赋值以后检查属性是否是对象,是对象则将属性转换为响应式的
that.walk(newValue)
// 数据变化后发送通知,触发watcher的pudate方法
dep.notify()
}
})
}
}