]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(watch): stop instance-bound watchers in post render queue
authorEvan You <yyx990803@gmail.com>
Tue, 7 Jul 2020 01:50:56 +0000 (21:50 -0400)
committerEvan You <yyx990803@gmail.com>
Tue, 7 Jul 2020 01:50:56 +0000 (21:50 -0400)
so that changes triggered in beforeUnmount get correct value in callback

fix #1525

packages/runtime-core/src/apiWatch.ts
packages/runtime-core/src/renderer.ts

index 4d98d425a8b403059cb8e9ea3e405ecb21a1cc91..bca2fbef18ccca48c98e404c572c43bc0130708f 100644 (file)
@@ -29,7 +29,6 @@ import {
   callWithErrorHandling,
   callWithAsyncErrorHandling
 } from './errorHandling'
-import { onBeforeUnmount } from './apiLifecycle'
 import { queuePostRenderEffect } from './renderer'
 import { warn } from './warning'
 
@@ -134,7 +133,8 @@ export function watch<T = any>(
 function doWatch(
   source: WatchSource | WatchSource[] | WatchEffect,
   cb: WatchCallback | null,
-  { immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ
+  { immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ,
+  instance = currentInstance
 ): WatchStopHandle {
   if (__DEV__ && !cb) {
     if (immediate !== undefined) {
@@ -160,8 +160,6 @@ function doWatch(
     )
   }
 
-  const instance = currentInstance
-
   let getter: () => any
   if (isArray(source)) {
     getter = () =>
@@ -316,9 +314,7 @@ export function instanceWatch(
   const getter = isString(source)
     ? () => publicThis[source]
     : source.bind(publicThis)
-  const stop = watch(getter, cb.bind(publicThis), options)
-  onBeforeUnmount(stop, this)
-  return stop
+  return doWatch(getter, cb.bind(publicThis), options, this)
 }
 
 function traverse(value: unknown, seen: Set<unknown> = new Set()) {
index 2c827136a9fcd0dab3e8980069b81a32694a11c2..0b3bd8318fe439fa5515251d8bc3103a3679af62 100644 (file)
@@ -1996,17 +1996,19 @@ function baseCreateRenderer(
     if (bum) {
       invokeArrayFns(bum)
     }
-    if (effects) {
-      for (let i = 0; i < effects.length; i++) {
-        stop(effects[i])
-      }
-    }
     // update may be null if a component is unmounted before its async
     // setup has resolved.
     if (update) {
       stop(update)
       unmount(subTree, instance, parentSuspense, doRemove)
     }
+    if (effects) {
+      queuePostRenderEffect(() => {
+        for (let i = 0; i < effects.length; i++) {
+          stop(effects[i])
+        }
+      }, parentSuspense)
+    }
     // unmounted hook
     if (um) {
       queuePostRenderEffect(um, parentSuspense)