part2 响应式原理
- Dep构造函数的实现
目的:
- 调用Dep.target(一个后续的Watcher)的addDep添加依赖方法。从而收集依赖
- 根据依赖精准的添加订阅者
- 分发通知给每个订阅者
Dep 发布-订阅器的作用:
- 提供add,remove等方法添加和取消订阅
- 提供notify方法,通知订阅者执行相关方法
- 提供depend 方法,收集依赖
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
| let uid = 0; class Dep { static target = null; constructor() { this.id = uid++ this.subs = [] } addSub(sub) { this.subs.push(sub) } removeSub(sub) { this.subs = this.subs.filter(item => { return item.id !== sub.id }) } notify() { const subs = this.subs.slice() subs.forEach(item => { item.update() }) } depend() { if (Dep.target) { Dep.target.addDep(this) } } }
const dep = new Dep()
dep.addSub({ id: "001", update() { console.log("通知001,更新状态") } }) dep.addSub({ id: "002", update() { console.log("通知002,更新状态") } }) dep.addSub({ id: "003", update() { console.log("通知003,更新状态") } }) dep.notify() dep.removeSub({ id: "002", update() { console.log("通知002,更新状态") } }) dep.notify()
|
- Observer 构造函数的实现-简化版,暂时只考虑对象
目的:处理被观察者对象,通过往它身上附加get/set来收集依赖和分发状态
- Observer 观察者类的作用:
- 实例化一个Dep,记录入参value,定义一个vmCount用于统计被使用次数
- 向入参添加一个__ob__属性,同时赋值dep,value,vmCount
- 遍历入参的键,调用defineReactive 设置反应性属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Observer { constructor(value) { this.value = value this.vmCount = 0 this.dep = new Dep() def(value, __ob__, this) this.walk(value) } walk(obj) { let keys = Object.keys(obj) for (let i = 0; i < keys.length; i++) { defineReactive(obj, keys[i]) } } }
|
- defineReactive 定义反应性属性方法的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <div id="app"> <p>{{ arr }}</p> </div> <script src="./vue.js"></script> <script> new Vue({ el:"#app", data:function (){ return { arr:[1,2,3], info:{ name:'tom', type:{ sort:"俄罗斯蓝猫", color:"blue" } } } }, }) </script>
|
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
| function defineReactive( obj, key, val, customSetter, shallow, ){ var dep = new Dep()
var childOb = !shallow && obsevrer(val)
Object.defineProperty({ obj, key, get(){
if(Dep.target){ dep.depend() if(childOb){ childOb.dep.depend() } } return value }, set(newValue){
value = newValue dep.notify() } }) }
|