Appearance
按这个结构改造
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()
}
}