Procházet zdrojové kódy

perf(reactivity): optimize effect stack

Evan You před 6 roky
rodič
revize
46c5393224

+ 5 - 6
packages/reactivity/src/computed.ts

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

+ 11 - 9
packages/reactivity/src/effect.ts

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