-
Notifications
You must be signed in to change notification settings - Fork 0
/
kvue.js
132 lines (109 loc) · 2.56 KB
/
kvue.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
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
132
function defineReactive(obj, key, val) {
// 递归
observe(val)
// 创建一个Dep和当前key一一对应
const dep = new Dep()
// 对传入obj进行访问拦截
Object.defineProperty(obj, key, {
get() {
console.log('get ' + key);
// 依赖收集在这里
Dep.target && dep.addDep(Dep.target)
return val
},
set(newVal) {
if (newVal !== val) {
console.log('set ' + key + ':' + newVal);
// 如果传入的newVal依然是obj,需要做响应化处理
observe(newVal)
val = newVal
// 通知更新
// watchers.forEach(w => w.update())
dep.notify()
}
}
})
}
function observe(obj) {
if (typeof obj !== 'object' || obj == null) {
// 希望传入的是obj
return
}
// 创建Observer实例
new Observer(obj)
}
// 代理函数,方便用户直接访问$data中的数据
function proxy(vm, sourceKey) {
// vm[sourceKey]就是vm[$data]
Object.keys(vm[sourceKey]).forEach(key => {
// 将$data中的key代理到vm属性中
Object.defineProperty(vm, key, {
get() {
return vm[sourceKey][key]
},
set(newVal) {
vm[sourceKey][key] = newVal
}
})
})
}
// 创建KVue构造函数
class KVue {
constructor(options) {
// 保存选项
this.$options = options;
this.$data = options.data;
// 响应化处理
observe(this.$data)
// 代理
proxy(this, '$data')
// 创建编译器
new Compiler(options.el, this)
}
}
// 根据对象类型决定如何做响应化
class Observer {
constructor(value) {
this.value = value
// 判断其类型
if (typeof value === 'object') {
this.walk(value)
}
}
// 对象数据响应化
walk(obj) {
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key])
})
}
// 数组数据响应化,待补充
}
// 观察者:保存更新函数,值发生变化调用更新函数
// const watchers = []
class Watcher {
constructor(vm, key, updateFn) {
this.vm = vm
this.key = key
this.updateFn = updateFn
// watchers.push(this)
// Dep.target静态属性上设置为当前watcher实例
Dep.target = this
this.vm[this.key] // 读取触发了getter
Dep.target = null // 收集完就置空
}
update() {
this.updateFn.call(this.vm, this.vm[this.key])
}
}
// Dep:依赖,管理某个key相关所有Watcher实例
class Dep {
constructor(){
this.deps = []
}
addDep(dep) {
this.deps.push(dep)
}
notify() {
this.deps.forEach(dep => dep.update())
}
}