瀏覽代碼

wip: disable tracking in all hooks

Evan You 6 年之前
父節點
當前提交
a6de6daa17
共有 3 個文件被更改,包括 20 次插入0 次删除
  1. 13 0
      packages/reactivity/src/effect.ts
  2. 2 0
      packages/reactivity/src/index.ts
  3. 5 0
      packages/runtime-core/src/apiLifecycle.ts

+ 13 - 0
packages/reactivity/src/effect.ts

@@ -107,11 +107,24 @@ function cleanup(effect: ReactiveEffect) {
   }
 }
 
+let shouldTrack = true
+
+export function pauseTracking() {
+  shouldTrack = false
+}
+
+export function resumeTracking() {
+  shouldTrack = true
+}
+
 export function track(
   target: any,
   type: OperationTypes,
   key?: string | symbol
 ) {
+  if (!shouldTrack) {
+    return
+  }
   const effect = activeReactiveEffectStack[activeReactiveEffectStack.length - 1]
   if (effect) {
     if (type === OperationTypes.ITERATE) {

+ 2 - 0
packages/reactivity/src/index.ts

@@ -12,6 +12,8 @@ export { computed, ComputedRef, ComputedOptions } from './computed'
 export {
   effect,
   stop,
+  pauseTracking,
+  resumeTracking,
   ITERATE_KEY,
   ReactiveEffect,
   ReactiveEffectOptions,

+ 5 - 0
packages/runtime-core/src/apiLifecycle.ts

@@ -8,6 +8,7 @@ import {
 import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
 import { warn } from './warning'
 import { capitalize } from '@vue/shared'
+import { pauseTracking, resumeTracking } from '@vue/reactivity'
 
 function injectHook(
   type: LifecycleHooks,
@@ -16,12 +17,16 @@ function injectHook(
 ) {
   if (target) {
     ;(target[type] || (target[type] = [])).push((...args: any[]) => {
+      // disable tracking inside all lifecycle hooks
+      // since they can potentially be called inside effects.
+      pauseTracking()
       // Set currentInstance during hook invocation.
       // This assumes the hook does not synchronously trigger other hooks, which
       // can only be false when the user does something really funky.
       setCurrentInstance(target)
       const res = callWithAsyncErrorHandling(hook, target, type, args)
       setCurrentInstance(null)
+      resumeTracking()
       return res
     })
   } else if (__DEV__) {