Skip to content

image

按这个结构改造

src/effect.js和03中一样

js
// effect/track.js
import { targetMap, activeEffect } from './effect.js'

import { TrackOpTypes, ITERATE_KEY } from '../utils/eunm.js'

/**
 * @type {boolean} 控制是否需要进行依赖收集
 */
let shouldTrack = true
export function pauseTracking() {
  shouldTrack = false
}
export function enableTracking() {
  shouldTrack = true
}

/**
 *  依赖收集器
 * @param target 原始对象
 * @param type 操作类型
 * @param key 操作的属性
 */
function track(target, type, key) {
  if (!shouldTrack) {
    return false
  }
     // 一层一层的查找,查找到后存储 
  let propMap = targetMap.get(target)  
  if (!propMap) { 
    targetMap.set(target, (propMap = new Map())) 
  }   

   // 如果是遍历的话,key 是 undefined
  if (type === TrackOpTypes.ITERATE) { 
    key = ITERATE_KEY
  } 

  let typeMap = propMap.get(key) 
  if (!typeMap) { 
    propMap.set(key, (typeMap = new Map())) 
  } 

   // 根据 type 值查找对应的 set
  let depSet = typeMap.get(type) 
  if (!depSet) { 
    depSet = new Set() 
    typeMap.set(type, depSet) 
  }

     // set 集合找到的话 存储依赖
  if (!depSet.has(activeEffect)) { 
    depSet.add(activeEffect) 
    activeEffect.deps.push(depSet) 
  }  
}
export { track }

js

 src/trigger.js

import { activeEffect, targetMap } from './effect.js'
import { triggerTypeMap, TriggerOpTypes, ITERATE_KEY } from '../utils/eunm.js'
/**
 *
 * @param target 原始对象
 * @param type 操作类型
 * @param key 操作的属性
 */

function trigger(target, type, key) {
     // 从设计好的数据结构里,一层一层的去找,找到对应的函数集合,然后全部执行一次
  const effectFns = getEffectFn(target, type, key)  
  if (!effectFns) return
  for (const effectFn of effectFns) {   
    if (effectFn === activeEffect) continue
    effectFn()  
  }  
}

/**
 * 根据 target type key 信息找到对应的依赖集合
 * @param target
 * @param type
 * @param key
 */
function getEffectFn(target, type, key) {  
  const propMap = targetMap.get(target)  
  if (!propMap) return
     // 如果是新增或者删除,会涉及到触发额外的迭代
  const keys = [key]  
  if (type === TriggerOpTypes.ADD || type === TriggerOpTypes.DELETE) {  
    keys.push(ITERATE_KEY)  
  }

  const effectFns = new Set()  // 存储依赖的函数
  for (const key of keys) {  
    const typeMap = propMap.get(key)  
    if (!typeMap) continue

    const trackTypes = triggerTypeMap[type]  
    for (const trackType of trackTypes) {  
      const dep = typeMap.get(trackType)  
      if (!dep) continue
      for (const effectFn of dep) {  
        effectFns.add(effectFn)  
      }  
    }  
  }  
  return effectFns  
}
export { trigger }

懒执行

传入的effect的回调会自动执行,修改这种行为

改造 effect.js,给传递参数

js
export function effect(fn, options = {}) {
  const { lazy } = options  
  const environment = () => {
    try {
      activeEffect = environment
      // 模拟真实的函数栈
      effectStack.push(environment)
      cleanup(environment)
      return fn()
    } finally {
      effectStack.pop()
      activeEffect = effectStack[effectStack.length - 1]
    }
  }
  environment.deps = [] // 记录该环境函数在哪些集合中使用

  if(!lazy) {  
    environment()  
  }  
  return environment  
}

如果传递了 lazy 返回函数交由控制权

手动派发更新

js
// effect.js
export function effect(fn, options = {}) {
  const { lazy } = options  
  const environment = () => {
    try {
      activeEffect = environment
      // 模拟真实的函数栈
      effectStack.push(environment)
      cleanup(environment)
      return fn()
    } finally {
      effectStack.pop()
      activeEffect = effectStack[effectStack.length - 1]
    }
  }
  environment.deps = [] // 记录该环境函数在哪些集合中使用
  environment.options = options  
  if(!lazy) {  
    environment()  
  }  
  return environment 
}
js
// trigger.js
function trigger(target, type, key) {
  //   从设计好的数据结构里,一层一层的去找,找到对应的函数集合,然后全部执行一次
  const effectFns = getEffectFn(target, type, key)
  if (!effectFns) return
  for (const effectFn of effectFns) {
    if (effectFn === activeEffect) continue
    // 如果传递了 scheduler ,交由外部手动更新
    if(effectFn.options && effect.options.scheduler) {  
      effect.options.scheduler(effectFn)  
    }  
    effectFn() 
  }
}

最后更新时间: