本文仅用于个人学习过程中的总结巩固
html
<div id="app">
{{name}} <!-- 发布者name属性内的订阅者1 -->
{{name}} <!-- 发布者name属性内的订阅者2 -->
{{name}} <!-- 发布者name属性内的订阅者3 -->
{{age}} <!-- 发布者age属性内的订阅者1 -->
</div>
js
const app = new Vue({
el: '#app',
data: {
name: 'sky', // 发布者-name属性
age: 18 // 发布者-age属性
}
})
当我们在项目开发中修改了data数据后,页面马上就能响应,这是如何做到的呢?
发布者与订阅者机制
// 发布者的类,包含多个方法
class Dep{
constructor() {
// subs = subscribers,订阅者列表
this.subs = []
}
// 增加一个订阅者
addSub(watcher) {
this.subs.push(watcher)
}
// 当监听的发布者变化时,调用此方法以更新所有订阅者
notify() {
this.subs.forEach(item => {
item.update()
})
}
}
// 订阅者的类
class Watcher {
constructor(name) {
this.name = name
}
// 更新当前订阅者数据
update() {
console.log(this.name + '发生update')
}
}
Observer及Compile
new Vue()
- Observer
- Compile
创建vue实例时,vue实例会将el及data分发给Observer及Compile进行处理
- Observer
用于监听劫持所有data属性,会进行以下处理
// 遍历data里所有属性
Object.keys(data).forEach(key => {
let value = data[key]
// Object.defineProperty方法,改变属性值
Object.defineProperty(data, key, {
set(newValue) { // 属性值改变时即调用此方法
console.log('监听' + key + '改变')
value = newValue
},
get() { // 获取属性值时即调用此方法
console.log('获取' + key + '的值')
return value
}
})
})
- Compile
解析el模板中的指令
<div id="app">
{{name}} <!-- 发布者name属性内的订阅者1 -->
{{name}} <!-- 发布者name属性内的订阅者2 -->
{{name}} <!-- 发布者name属性内的订阅者3 -->
{{age}} <!-- 发布者age属性内的订阅者1 -->
</div>
1、Observer会对每一个data内的属性都创建一个Dep对象(“发布者”)
2、Compile解析el模板中的指令,如果指令有对应符合的data属性名,则先会创建一个Watcher的实例对象,并将其作为“订阅者”加入该Dep对象(“发布者”)的subs数组中
3、当data内属性的值发生变化时,监听的Observer会调用其中的set方法,在set方法里再调用notify方法,notify方法则是将当前Dep对象内的所有“订阅者”循环并执行每一个自身的update方法以进行数据更新。