vue 双向绑定简单实现

深入响应式原理

深入响应式原理

vue 双向绑定简单实现

待更新,需要考虑proxy,代理通知,同步问题,虚拟dom问题

先考虑简单的情况

1
2
3
4
5
6
7
8
9
10
11
class Vue {
constructor(options) {
this.$options = options
this._data = options.data
observe(options.data, this._update)
this._update()
}
_update(options) {
this.$options.render()
}
}

Observe

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
class Observe {
constructor(value, sub) {
if (Array.isArray(value)) {
this.observeArry(value, sub)
} else {
this.walk(obj, sub)
}
}
//defineproperty,每个对象
walk(obj, sub) {
const keys = Object.keys(obj)
for (let i = 0, len = keys; i < len; i++) {
defineReactive(obj, keys[i], obj[keys[i]], sub)
}
}
observeArry(items) {
//...
}
}
function observe(value, sub) {
new Observe(value, sub)
}
class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
removeSub(sub) {
this.subs = this.subs.filter(item => item !== sub)//vue中采用splice不知道是否有特殊的意义
}
notify() {
const subs = this.subs.slice()
for (let i = 0, l = subs.length; i < l; i++) {
subs[i].update()
}
}
}
Dep.target = null

defineReactive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function defineReactive(obj, key, val) {
const dep = new Dep()
Object.defineProperty(obj, key, {
writable: true,
enumerable: true,
get: function getter() {
return val
},
set: function setter(newVal) {
if(val===newVal){
return
}
val = newVal
dep.notify()
}
})
}

Watcher

1
2
3
4
5
6
7
8
9
class Wacher {
constructor() {
}
update() {
}
}