zoukankan      html  css  js  c++  java
  • 依赖追踪算法

    依赖追踪算法

    简单理解就是当我们有一个数据需要跟随一个数据时,需要用到,
    例如数据A更新时,B自动跟随更新

     
    Reactive 本质上在 set Reactive 时去执行更新
    Computed 本质上在 get Reactive 时标记依赖

    Computed 函数 C 初次求值时,标记 C
    对 C 求值过程中,获取 Reactive 的值,各 Reactive 的 getter 被触发
    为每个 Reactive 维护一个依赖者 deps 数组,将 C 添加至数组内
    求值完成后,标记清空,返回求值结果
    Reactive 更新时,各 deps 中 C 均在 Reactive setter 中触发,一并更新

    例子

    	/**
    	* computed 实现机制
    	* 1. computed 初次求值(被 get)时,将全局变量 Dep 标记为自身
    	* 2. 在该 getter 中使用 computed 函数计算 value
    	* 3. computed 函数中包含了对各 reactive 的引用
    	* 4. 在该 computed 中对 reactive 求值(触发 getter)时,各 reactive 收集当前 Dep 至自身的 deps 数组。
    	*    computed 求值完成后,所有它所依赖的 reactive 均完成对该 computed 的依赖收集
    	* 6. 求值完成后,computed 将 Dep 标记为空,返回求值结果作为 computed 的值
    	* 7. 下次 reactive 更新时,所有依赖它的 computed 在该 reactive 的 setter 中一并更新
    	*/
    	
    	
    	// 标记当前依赖的全局单例
    	// 由 computed 的 getter 触发时设入该值
    	// 在 computed 求值期间,computed 依赖的 reactive 通过该值收集该 computed 至其依赖中
    	// 当 computed 求值完成后再将此值置空
    	let Dep = null
    	
    	// 通过设置 getter 与 setter 定义 computed
    	// computeFn 为通过 reactive 求值出 computed 的求值函数
    	// updateCallback 为 computed 更新时触发的回调
    	function defineComputed (obj, key, computeFn, updateCallback) {
    	 // 封装供 reactive 收集的更新回调
    	 // 用于触发 computed 的更新事件
    	 const onDependencyUpdated = function () {
    	   // 在此计算出的值没有用于更新 computed
    	   // 而是用于触发 computed 的更新事件
    	   // 供后续可能的 watch 等模块使用
    	   const value = computeFn()
    	   updateCallback(value)
    	 }
    	 Object.defineProperty(obj, key, {
    	   get () {
    		 // 标记当前依赖,供 reactive 收集
    		 Dep = onDependencyUpdated
    		 // 在 computeFn 中对 reactive 求值时
    		 // 由 reactive 的 setter 收集当前 computed 依赖
    		 // 故完成对 computed 的初次求值时,即完成了 reactive 的依赖收集
    		 const value = computeFn()
    		 // 完成求值后,清空标记
    		 Dep = null
    		 // 最终返回的 getter 结果
    		 return value
    	   },
    	   // 计算属性无法 set
    	   set () {}
    	 })
    	}
    	
    	// 通过 getter 与 setter 定义出一个 reactive
    	function defineReactive (obj, key, val = null) {
    	 // 在此标记哪些 computed 依赖了该 reactive
    	 const deps = []
    	
    	 Object.defineProperty(obj, key, {
    	   // 为 reactive 求值时,收集其依赖
    	   get () {
    		 if (Dep) deps.push(Dep)
    		 // 返回 val 值作为 getter 求值结果
    		 return val
    	   },
    	   // 为 reactive 赋值时,更新所有依赖它的计算属性
    	   set (newValue) {
    		 // 在 setter 中更新值
    		 val = newValue
    		 // 更新值后触发所有 computed 依赖更新
    		 deps.forEach(changeFn => changeFn())
    	   }
    	 })
    	}
    	
    	const elder = {}
    	defineReactive(elder, 'now')
    	
    	defineComputed(elder, 'age',
    	 () => elder.now - 1926,
    	 () => console.log('Now his age is',elder.age)
    	)
    	
    	elder.now = 2016
    	console.log(elder.age)
    	
    	elder.now = 2017
    	//把console.log换成对html模板的渲染,我们就能发现reactive更新的时候,computed也进行了更新
    	console.log(elder.age)
    	
    
  • 相关阅读:
    Celery
    Xadmin的基本使用 补充:admin控制user字段
    Python pip换源 创建虚拟环境 luffy项目配置(数据库bug)
    gitignore 文件 刷新
    django python mange.py runserver 源码
    leetcode125. 验证回文串 python 简单
    leetcode1028 从先序遍历还原二叉树 python 100%内存 一次遍历
    fiddler
    xpath
    linux常用命令
  • 原文地址:https://www.cnblogs.com/lovecode3000/p/12422321.html
Copyright © 2011-2022 走看看