前提:实际开发中,响应式对象肯定是不止一个对象的, 使用数组reactiveFns, 所有依赖的函数都放到数组里面,是满足不了多个响应式对象,使用类单独来管理一个对象所有的依赖
1. 响应式依赖收集-类
- 1.1. 类结构:创建Depend类来管理响应式依赖,包含reactiveFns数组存储依赖函数
- 1.2. 核心方法:
- addDepend(fn):添加依赖函数到数组,会先判断fn是否存在
- notify():遍历执行所有收集的依赖函数
- 代码如下:
// 使用类单独来管理一个对象所有的依赖
class Depend {
constructor() {
this.reactiveFns = [];
}
addDepend (fn) {
if(fn) {
// 将依赖函数添加到数组,
this.reactiveFns.push(fn);
}
}
notify () {
this.reactiveFns.forEach(fn => {
// 遍历执行所有收集的依赖函数
fn()
})
}
}
- 1.3. 优势: 相比单一数组管理,可以针对不同对象创建独立的Depend实例,避免所有依赖混在一起
- 1.4. 执行过程
- 创建Depend实例:const dep = new Depend()
- 收集依赖:通过watchFn函数调用dep.addDepend(fn)
- 触发更新:修改属性后手动调用dep.notify()
- 示例代码如下:
// 创建Depend实例 const dep = new Depend() function watchFn (fn) { dep.addDepend(fn) // 传入函数后立即执行一次,类似watchEffect() fn() } // 响应式函数 watchFn(function foo () { console.log('foo: ', obj.name); console.log('foo: ', obj.age); console.log('foo function'); }) watchFn(function bar () { console.log('bar: ', obj.name + ' hello'); console.log('bar: ', obj.age + 10); console.log('bar function'); }) // 修改obj的属性 obj.name = 'kobe' // 当依赖发生变化时,会执行对应的响应式函数 dep.notify() ```
- 1.5. 当前问题:
- 每次属性修改后需要手动调用
dep.notify()
- 容易遗漏导致依赖不更新
- 多个属性变更时需要多次调用
// 参考上面的代码...
// 修改obj的属性
console.log('name发生变化时----------------------------------------');
obj.name = 'kobe'
// 当依赖发生变化时,会执行对应的响应式函数
dep.notify()
// 再次修改obj的属性
obj.name = 'james'
// 每次手动通知,一旦忘记就不是响应式了
// dep.notify()
-
- 完整代码如下:
// 使用类单独来管理一个对象所有的依赖 class Depend { constructor() { this.reactiveFns = []; } addDepend (fn) { if(fn) { // 将依赖函数添加到数组, this.reactiveFns.push(fn); } } notify () { this.reactiveFns.forEach(fn => { // 遍历执行所有收集的依赖函数 fn() }) } } // 实际开发中,响应式对象肯定是不止一个对象的 // 例如: // const user = { nickName: 'kobe', level: 100 } // const product = { name: '电脑', price: 1000 } // 有一个弊端,只有一个数组reactiveFns, 所有依赖的函数都放到数组里面,是满足不了多个响应式对象 // 例如:一旦修改了product.name所有的响应式函数都会执行,目标是只想要执行product.name的响应式函数 const obj = { name: 'why', age: 18 } // 当上面有很多依赖函数时,很难收集 // 设置一个专门执行响应式函数的一个函数 const dep = new Depend() // obj => new Depend() // user => new Depend() // product => new Depend() function watchFn (fn) { dep.addDepend(fn) // 传入函数后立即执行一次,类似watchEffect() fn() } watchFn(function foo () { console.log('foo: ', obj.name); console.log('foo: ', obj.age); console.log('foo function'); }) watchFn(function bar () { console.log('bar: ', obj.name + ' hello'); console.log('bar: ', obj.age + 10); console.log('bar function'); }) // 修改obj的属性 console.log('name发生变化时----------------------------------------'); obj.name = 'kobe' // 当依赖发生变化时,会执行对应的响应式函数 dep.notify() // 修改obj的属性 console.log('age发生变化时----------------------------------------'); obj.age = 20 dep.notify() console.log('name发生变化时----------------------------------------'); obj.name = 'james' // 每次手动通知,一旦忘记就不是响应式了 // dep.notify() ```
- 1.7. 后续改进:
- 将展示如何自动创建依赖收集器
- 实现属性变更自动通知机制