响应式原理二:响应式依赖收集

发布于:2025-07-11 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、响应式依赖收集

  1. 依赖收集机制:
    • 1.1. 存储结构:使用数组reactiveFns存储所有依赖函数
    • 1.2. 注册函数:通过watchFn函数将依赖函数注册到数组中
    • 1.3. 自动执行:注册时会立即执行一次函数,确保初始状态正确
    • 示例代码如下:
      // 设置一个专门执行响应式函数的一个函数
      const reactiveFns = []
      function watchFn (fn) {
        // 把所有依赖的东西,统一收集到一个数组中(reactiveFns), 方便进行管理
        reactiveFns.push(fn)
        // 传入函数后立即执行一次,类似watchEffect()
        fn()
      }   
      
  2. 应用示例:
    • 2.1. 当对象属性obj.nameobj.age变化时
    • 2.2. 自动执行所有依赖这些属性的函数(如foo()bar()
    • 2.3.通过遍历reactiveFns数组统一执行所有依赖函数
    •    	const obj = {
        	  name: 'why',
        	  age: 18
        	}
        	// 设置一个专门执行响应式函数的一个函数
        	const reactiveFns = []
        	function watchFn (fn) {
        	  // 把所有依赖的东西,统一收集到一个数组中(reactiveFns), 方便进行管理
        	  reactiveFns.push(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'
      
        // 当依赖发生变化时,会执行对应的响应式函数
        reactiveFns.forEach(fn => {
          fn()
        }) 
      
  3. 执行流程:
    • 3.1. 属性修改触发更新
    • 3.2. 从依赖数组中取出所有相关函数
    • 3.3.依次执行每个依赖函数
  4. 设计特点:
    • 4.1. 手动收集:目前需要显式调用watchFn注册依赖函数
    • 4.2. 统一管理:所有依赖函数集中存储在数组中便于统一触发
    • 4.3. 自动执行:注册时立即执行确保初始状态,变化时再次执行更新状态
  5. watchFnVue的关系:
    • 5.1. 类似Vue3的watchEffect机制
    • 5.2. 区别在于当前实现是手动收集依赖
    • 5.3. 后续会优化为自动依赖收集
    1. 完整代码如下:
    const obj = {
      name: 'why',
      age: 18
    }
    
    
    // function foo () {
    //   console.log('foo: ', obj.name);
    //   console.log('foo: ', obj.age);
    //   console.log('foo function');
    // }
    
    
    // function bar () {
    //   console.log('bar: ', obj.name + ' hello');
    //   console.log('bar: ', obj.age + 10);
    //   console.log('bar function');
    // }
    
    // 当上面有很多依赖函数时,很难收集
    // 设置一个专门执行响应式函数的一个函数
    const reactiveFns = []
    function watchFn (fn) {
      // 把所有依赖的东西,统一收集到一个数组中(reactiveFns), 方便进行管理
      reactiveFns.push(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');
    })
    
    watchFn(() => {
      // 传入空函数时,最终是不会加入响应里面
    })
    
    // 修改obj的属性
    console.log('name发生变化时----------------------------------------');
    obj.name = 'kobe'
    // foo()
    // bar()
      // 当依赖发生变化时,会执行对应的响应式函数
      reactiveFns.forEach(fn => {
        fn()
      })
    

小结

知识点 核心内容 易混淆点/难点 代码示例/关键实现
响应式机制原理 通过监听对象属性变化触发依赖函数重新执行 手动收集依赖 vs 自动收集依赖 watchFn(fn) 函数封装与依赖数组管理
依赖收集实现 将依赖函数统一存入 reactiveFns 数组,属性变化时遍历执行 依赖函数初次执行时机(立即执行 vs 延迟执行) reactiveFns.push(fn); fn()
WatchFn 设计 函数注册机制:标记需响应式的函数并自动执行一次 非响应式函数误注册问题(后续优化点) watchFn(() => { console.log(obj.name) })
响应式触发流程 1. 修改属性值 → 2. 从依赖数组提取函数 → 3. 批量执行 多属性依赖时的执行效率(未优化) obj.name = “copy” 触发 foo() 和 bar()
与 WatchEffect 对比 类似 Vue 的 watchEffect,但依赖需手动声明 自动依赖追踪的实现差异(当前未实现) 无自动依赖关系分析

网站公告

今日签到

点亮在社区的每一天
去签到