Vue的响应式原理主要分为两大部分
- 修改数据,Vue内部监听数据的改变(Object.defineProperty 监听对象属性改变)
- 发布者订阅者模式
监听数据的改变
声明一个对象,然后对该对象的key进行遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
const obj = {
message:'我是data里的属性1',
name:'我是data里的属性2'
}
Object.keys(obj).forEach(key=>{
let value = obj[key]
Object.defineProperty(obj,key,{
set(newValue){
// key改变时会调用set方法
value = newValue
},
get(){
// 获取key对应的值时会调用get方法,如控制台输入obj.name
return value
}
})
})
|
Object.defineProperty里的:
- set方法根据解析Html,获取哪些地方用到了这个属性
- get方法将值返回给用到该属性的每个地方
发布者订阅者模式
发布者:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Dep {
constructor() {
this.subs = []
}
addSub(watcher) {
this.subs.push(watcher)
}
notify() {
this.subs.forEach(item => {
item.update()
})
}
}
const dep = new Dep()
|
订阅者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Watcher {
constructor(name) {
this.name = name
}
update() {
console.log(this.name + 'update了');
}
}
const w1 = new Watcher('张三')
dep.addSub(w1)
const w2 = new Watcher('李四')
dep.addSub(w2)
const w3 = new Watcher('王五')
dep.addSub(w3)
// 发布
dep.notify()
|
说下这个过程吧:
- new了一个发布者
dep
,一个data
属性会对应一个不同的dep
- new了订阅者(相当于Vue实例中的每一个用到data其中一个属性的地方,给它们每个人都起个名字),例如new了
w1
之后,会调用发布者dep.addSub()
方法(在Object.defineProperty
的get
方法中调用),让其真正成为发布者的订阅者(加入到订阅者数组中)
- 当某个订阅者值发生改变时,会调用发布者
dep.notify()
方法,通知所有订阅者它们的值发生改变了,执行订阅者的update()
。
- 于是乎,当值发生改变时,在
Object.defineProperty
的set
方法中,就会调用dep.notify()
来更新所有订阅者的值
图解响应式原理
1
2
3
4
5
6
|
new Vue({
el:'#app',
data:{
}
})
|
- el会走Compile过程,data会走Observer过程
- Observer即
Object.defineProperty
言语都在图中(我这字简直不像研究生写出来的- -!)