fix(watch): stop instance-bound watchers in post render queue

so that changes triggered in beforeUnmount get correct value in callback

fix #1525
This commit is contained in:
Evan You 2020-07-06 21:50:56 -04:00
parent 41db49dfb7
commit 58b07069ad
2 changed files with 10 additions and 12 deletions

View File

@ -29,7 +29,6 @@ import {
callWithErrorHandling, callWithErrorHandling,
callWithAsyncErrorHandling callWithAsyncErrorHandling
} from './errorHandling' } from './errorHandling'
import { onBeforeUnmount } from './apiLifecycle'
import { queuePostRenderEffect } from './renderer' import { queuePostRenderEffect } from './renderer'
import { warn } from './warning' import { warn } from './warning'
@ -134,7 +133,8 @@ export function watch<T = any>(
function doWatch( function doWatch(
source: WatchSource | WatchSource[] | WatchEffect, source: WatchSource | WatchSource[] | WatchEffect,
cb: WatchCallback | null, cb: WatchCallback | null,
{ immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ { immediate, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ,
instance = currentInstance
): WatchStopHandle { ): WatchStopHandle {
if (__DEV__ && !cb) { if (__DEV__ && !cb) {
if (immediate !== undefined) { if (immediate !== undefined) {
@ -160,8 +160,6 @@ function doWatch(
) )
} }
const instance = currentInstance
let getter: () => any let getter: () => any
if (isArray(source)) { if (isArray(source)) {
getter = () => getter = () =>
@ -316,9 +314,7 @@ export function instanceWatch(
const getter = isString(source) const getter = isString(source)
? () => publicThis[source] ? () => publicThis[source]
: source.bind(publicThis) : source.bind(publicThis)
const stop = watch(getter, cb.bind(publicThis), options) return doWatch(getter, cb.bind(publicThis), options, this)
onBeforeUnmount(stop, this)
return stop
} }
function traverse(value: unknown, seen: Set<unknown> = new Set()) { function traverse(value: unknown, seen: Set<unknown> = new Set()) {

View File

@ -1996,17 +1996,19 @@ function baseCreateRenderer(
if (bum) { if (bum) {
invokeArrayFns(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 // update may be null if a component is unmounted before its async
// setup has resolved. // setup has resolved.
if (update) { if (update) {
stop(update) stop(update)
unmount(subTree, instance, parentSuspense, doRemove) unmount(subTree, instance, parentSuspense, doRemove)
} }
if (effects) {
queuePostRenderEffect(() => {
for (let i = 0; i < effects.length; i++) {
stop(effects[i])
}
}, parentSuspense)
}
// unmounted hook // unmounted hook
if (um) { if (um) {
queuePostRenderEffect(um, parentSuspense) queuePostRenderEffect(um, parentSuspense)