perf(reactivity): optimize effect stack

This commit is contained in:
Evan You 2019-12-13 23:06:55 -05:00
parent 49a50d3c9c
commit 46c5393224
2 changed files with 16 additions and 15 deletions

View File

@ -1,4 +1,4 @@
import { effect, ReactiveEffect, effectStack } from './effect' import { effect, ReactiveEffect, activeEffect } from './effect'
import { Ref, UnwrapRef } from './ref' import { Ref, UnwrapRef } from './ref'
import { isFunction, NOOP } from '@vue/shared' import { isFunction, NOOP } from '@vue/shared'
@ -73,15 +73,14 @@ export function computed<T>(
} }
function trackChildRun(childRunner: ReactiveEffect) { function trackChildRun(childRunner: ReactiveEffect) {
if (effectStack.length === 0) { if (activeEffect === undefined) {
return return
} }
const parentRunner = effectStack[effectStack.length - 1]
for (let i = 0; i < childRunner.deps.length; i++) { for (let i = 0; i < childRunner.deps.length; i++) {
const dep = childRunner.deps[i] const dep = childRunner.deps[i]
if (!dep.has(parentRunner)) { if (!dep.has(activeEffect)) {
dep.add(parentRunner) dep.add(activeEffect)
parentRunner.deps.push(dep) activeEffect.deps.push(dep)
} }
} }
} }

View File

@ -40,7 +40,8 @@ export interface DebuggerEventExtraInfo {
oldTarget?: Map<any, any> | Set<any> oldTarget?: Map<any, any> | Set<any>
} }
export const effectStack: ReactiveEffect[] = [] const effectStack: ReactiveEffect[] = []
export let activeEffect: ReactiveEffect | undefined
export const ITERATE_KEY = Symbol('iterate') export const ITERATE_KEY = Symbol('iterate')
@ -95,9 +96,11 @@ function run(effect: ReactiveEffect, fn: Function, args: unknown[]): unknown {
cleanup(effect) cleanup(effect)
try { try {
effectStack.push(effect) effectStack.push(effect)
activeEffect = effect
return fn(...args) return fn(...args)
} finally { } finally {
effectStack.pop() effectStack.pop()
activeEffect = effectStack[effectStack.length - 1]
} }
} }
} }
@ -123,10 +126,9 @@ export function resumeTracking() {
} }
export function track(target: object, type: TrackOpTypes, key: unknown) { export function track(target: object, type: TrackOpTypes, key: unknown) {
if (!shouldTrack || effectStack.length === 0) { if (!shouldTrack || activeEffect === undefined) {
return return
} }
const effect = effectStack[effectStack.length - 1]
let depsMap = targetMap.get(target) let depsMap = targetMap.get(target)
if (depsMap === void 0) { if (depsMap === void 0) {
targetMap.set(target, (depsMap = new Map())) targetMap.set(target, (depsMap = new Map()))
@ -135,12 +137,12 @@ export function track(target: object, type: TrackOpTypes, key: unknown) {
if (dep === void 0) { if (dep === void 0) {
depsMap.set(key, (dep = new Set())) depsMap.set(key, (dep = new Set()))
} }
if (!dep.has(effect)) { if (!dep.has(activeEffect)) {
dep.add(effect) dep.add(activeEffect)
effect.deps.push(dep) activeEffect.deps.push(dep)
if (__DEV__ && effect.options.onTrack) { if (__DEV__ && activeEffect.options.onTrack) {
effect.options.onTrack({ activeEffect.options.onTrack({
effect, effect: activeEffect,
target, target,
type, type,
key key