From e747d5e88841c3a0f2c59956399b21fbc084bea7 Mon Sep 17 00:00:00 2001 From: Ronald Rogers Date: Wed, 7 Aug 2019 18:21:33 -0400 Subject: [PATCH 01/10] fix(ssr): Memory leak in poll method, take 2 (fix #2606) --- flow/declarations.js | 1 + src/components/view.js | 7 +++++++ src/create-route-map.js | 1 + src/history/base.js | 38 ++++++++++++-------------------------- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/flow/declarations.js b/flow/declarations.js index 942aa73bf..554e214f1 100644 --- a/flow/declarations.js +++ b/flow/declarations.js @@ -68,6 +68,7 @@ declare type RouteRecord = { regex: RouteRegExp; components: Dictionary; instances: Dictionary; + pendingCbs: Dictionary; name: ?string; parent: ?RouteRecord; redirect: ?RedirectOption; diff --git a/src/components/view.js b/src/components/view.js index 3f440d5b4..b672ccc04 100644 --- a/src/components/view.js +++ b/src/components/view.js @@ -1,5 +1,6 @@ import { warn } from '../util/warn' import { extend } from '../util/misc' +import { tryFinalizeTransition } from '../history/base' export default { name: 'RouterView', @@ -63,6 +64,10 @@ export default { (!val && current === vm) ) { matched.instances[name] = val + // if the route transition has already been confirmed then we weren't + // able to call the cb during confirmation as the component was not + // registered yet, so we call it here. + tryFinalizeTransition(matched, name) } } @@ -70,6 +75,7 @@ export default { // in case the same component instance is reused across different routes ;(data.hook || (data.hook = {})).prepatch = (_, vnode) => { matched.instances[name] = vnode.componentInstance + tryFinalizeTransition(matched, name) } // register instance in init hook @@ -80,6 +86,7 @@ export default { vnode.componentInstance !== matched.instances[name] ) { matched.instances[name] = vnode.componentInstance + tryFinalizeTransition(matched, name) } } diff --git a/src/create-route-map.js b/src/create-route-map.js index 0f790108c..6d9608fbb 100644 --- a/src/create-route-map.js +++ b/src/create-route-map.js @@ -73,6 +73,7 @@ function addRouteRecord ( regex: compileRouteRegex(normalizedPath, pathToRegexpOptions), components: route.components || { default: route.component }, instances: {}, + pendingCbs: {}, name, parent, matchAs, diff --git a/src/history/base.js b/src/history/base.js index 2b12e1967..2eff355a0 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -178,10 +178,9 @@ export class History { runQueue(queue, iterator, () => { const postEnterCbs = [] - const isValid = () => this.current === route // wait until async components are resolved before // extracting in-component enter guards - const enterGuards = extractEnterGuards(activated, postEnterCbs, isValid) + const enterGuards = extractEnterGuards(activated, postEnterCbs) const queue = enterGuards.concat(this.router.resolveHooks) runQueue(queue, iterator, () => { if (this.pending !== route) { @@ -299,13 +298,12 @@ function bindGuard (guard: NavigationGuard, instance: ?_Vue): ?NavigationGuard { function extractEnterGuards ( activated: Array, cbs: Array, - isValid: () => boolean ): Array { return extractGuards( activated, 'beforeRouteEnter', (guard, _, match, key) => { - return bindEnterGuard(guard, match, key, cbs, isValid) + return bindEnterGuard(guard, match, key, cbs) } ) } @@ -315,18 +313,15 @@ function bindEnterGuard ( match: RouteRecord, key: string, cbs: Array, - isValid: () => boolean ): NavigationGuard { return function routeEnterGuard (to, from, next) { return guard(to, from, cb => { if (typeof cb === 'function') { + match.pendingCbs[key] = cb cbs.push(() => { - // #750 - // if a router-view is wrapped with an out-in transition, - // the instance may not have been registered at this time. - // we will need to poll for registration until current route - // is no longer valid. - poll(cb, match.instances, key, isValid) + // if the instance is registered call the cb here, otherwise it will + // get called when it is registered in the component's lifecycle hooks + tryFinalizeTransition(match, key) }) } next(cb) @@ -334,20 +329,11 @@ function bindEnterGuard ( } } -function poll ( - cb: any, // somehow flow cannot infer this is a function - instances: Object, - key: string, - isValid: () => boolean -) { - if ( - instances[key] && - !instances[key]._isBeingDestroyed // do not reuse being destroyed instance - ) { - cb(instances[key]) - } else if (isValid()) { - setTimeout(() => { - poll(cb, instances, key, isValid) - }, 16) +export function tryFinalizeTransition (record: RouteRecord, name: string) { + if (record.instances[name] && record.pendingCbs[name]) { + const instance = record.instances[name] + const cb = record.pendingCbs[name] + delete record.pendingCbs[name] + cb(instance) } } From 062a5aa29c2b1dae5b08d585608f82fb62c5dede Mon Sep 17 00:00:00 2001 From: Ronald Rogers Date: Wed, 7 Aug 2019 20:52:47 -0400 Subject: [PATCH 02/10] fix: cb called before data init in keep-alive view and mixin guards not being called --- flow/declarations.js | 2 +- src/components/view.js | 9 ++++----- src/history/base.js | 16 +++++----------- src/util/route.js | 11 +++++++++++ 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/flow/declarations.js b/flow/declarations.js index 554e214f1..68c2543f9 100644 --- a/flow/declarations.js +++ b/flow/declarations.js @@ -68,7 +68,7 @@ declare type RouteRecord = { regex: RouteRegExp; components: Dictionary; instances: Dictionary; - pendingCbs: Dictionary; + pendingCbs: Dictionary>; name: ?string; parent: ?RouteRecord; redirect: ?RedirectOption; diff --git a/src/components/view.js b/src/components/view.js index b672ccc04..9e2d54333 100644 --- a/src/components/view.js +++ b/src/components/view.js @@ -1,6 +1,6 @@ import { warn } from '../util/warn' import { extend } from '../util/misc' -import { tryFinalizeTransition } from '../history/base' +import { tryFinalizeTransition } from '../util/route' export default { name: 'RouterView', @@ -64,10 +64,6 @@ export default { (!val && current === vm) ) { matched.instances[name] = val - // if the route transition has already been confirmed then we weren't - // able to call the cb during confirmation as the component was not - // registered yet, so we call it here. - tryFinalizeTransition(matched, name) } } @@ -75,6 +71,9 @@ export default { // in case the same component instance is reused across different routes ;(data.hook || (data.hook = {})).prepatch = (_, vnode) => { matched.instances[name] = vnode.componentInstance + // if the route transition has already been confirmed then we weren't + // able to call the cb during confirmation as the component was not + // registered yet, so we call it here. tryFinalizeTransition(matched, name) } diff --git a/src/history/base.js b/src/history/base.js index 2eff355a0..5ac52e692 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -5,7 +5,7 @@ import type Router from '../index' import { inBrowser } from '../util/dom' import { runQueue } from '../util/async' import { warn, isError, isExtendedError } from '../util/warn' -import { START, isSameRoute } from '../util/route' +import { START, isSameRoute, tryFinalizeTransition } from '../util/route' import { flatten, flatMapComponents, @@ -317,7 +317,10 @@ function bindEnterGuard ( return function routeEnterGuard (to, from, next) { return guard(to, from, cb => { if (typeof cb === 'function') { - match.pendingCbs[key] = cb + if (!match.pendingCbs[key]) { + match.pendingCbs[key] = [] + } + match.pendingCbs[key].push(cb) cbs.push(() => { // if the instance is registered call the cb here, otherwise it will // get called when it is registered in the component's lifecycle hooks @@ -328,12 +331,3 @@ function bindEnterGuard ( }) } } - -export function tryFinalizeTransition (record: RouteRecord, name: string) { - if (record.instances[name] && record.pendingCbs[name]) { - const instance = record.instances[name] - const cb = record.pendingCbs[name] - delete record.pendingCbs[name] - cb(instance) - } -} diff --git a/src/util/route.js b/src/util/route.js index 54a91a738..79d8fcee5 100644 --- a/src/util/route.js +++ b/src/util/route.js @@ -130,3 +130,14 @@ function queryIncludes (current: Dictionary, target: Dictionary) } return true } + +export function tryFinalizeTransition (record: RouteRecord, name: string) { + if (record.instances[name] && record.pendingCbs[name]) { + const instance = record.instances[name] + const cbs = record.pendingCbs[name] + delete record.pendingCbs[name] + for (let i = 0; i < cbs.length; i++) { + cbs[i](instance) + } + } +} From 71d0088bbbc42454e94467ba0ccfb09e76c4e271 Mon Sep 17 00:00:00 2001 From: Ronald Rogers Date: Thu, 8 Aug 2019 00:46:07 -0400 Subject: [PATCH 03/10] refactor: renamed things for clarity --- flow/declarations.js | 2 +- src/components/view.js | 7 ++++--- src/history/base.js | 16 ++++++++-------- src/util/route.js | 8 ++++---- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/flow/declarations.js b/flow/declarations.js index 68c2543f9..ee1a10283 100644 --- a/flow/declarations.js +++ b/flow/declarations.js @@ -68,7 +68,7 @@ declare type RouteRecord = { regex: RouteRegExp; components: Dictionary; instances: Dictionary; - pendingCbs: Dictionary>; + enteredCbs: Dictionary>; name: ?string; parent: ?RouteRecord; redirect: ?RedirectOption; diff --git a/src/components/view.js b/src/components/view.js index 9e2d54333..e64be5156 100644 --- a/src/components/view.js +++ b/src/components/view.js @@ -1,6 +1,6 @@ import { warn } from '../util/warn' import { extend } from '../util/misc' -import { tryFinalizeTransition } from '../util/route' +import { handleRouteEntered } from '../util/route' export default { name: 'RouterView', @@ -74,7 +74,8 @@ export default { // if the route transition has already been confirmed then we weren't // able to call the cb during confirmation as the component was not // registered yet, so we call it here. - tryFinalizeTransition(matched, name) + matched.enteredCbs + handleRouteEntered(matched, name) } // register instance in init hook @@ -85,7 +86,7 @@ export default { vnode.componentInstance !== matched.instances[name] ) { matched.instances[name] = vnode.componentInstance - tryFinalizeTransition(matched, name) + handleRouteEntered(matched, name) } } diff --git a/src/history/base.js b/src/history/base.js index 5ac52e692..9072ceeba 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -5,7 +5,7 @@ import type Router from '../index' import { inBrowser } from '../util/dom' import { runQueue } from '../util/async' import { warn, isError, isExtendedError } from '../util/warn' -import { START, isSameRoute, tryFinalizeTransition } from '../util/route' +import { START, isSameRoute, handleRouteEntered } from '../util/route' import { flatten, flatMapComponents, @@ -177,10 +177,10 @@ export class History { } runQueue(queue, iterator, () => { - const postEnterCbs = [] + const enteredCbs = [] // wait until async components are resolved before // extracting in-component enter guards - const enterGuards = extractEnterGuards(activated, postEnterCbs) + const enterGuards = extractEnterGuards(activated, enteredCbs) const queue = enterGuards.concat(this.router.resolveHooks) runQueue(queue, iterator, () => { if (this.pending !== route) { @@ -190,7 +190,7 @@ export class History { onComplete(route) if (this.router.app) { this.router.app.$nextTick(() => { - postEnterCbs.forEach(cb => { + enteredCbs.forEach(cb => { cb() }) }) @@ -317,14 +317,14 @@ function bindEnterGuard ( return function routeEnterGuard (to, from, next) { return guard(to, from, cb => { if (typeof cb === 'function') { - if (!match.pendingCbs[key]) { - match.pendingCbs[key] = [] + if (!match.enteredCbs[key]) { + match.enteredCbs[key] = [] } - match.pendingCbs[key].push(cb) + match.enteredCbs[key].push(cb) cbs.push(() => { // if the instance is registered call the cb here, otherwise it will // get called when it is registered in the component's lifecycle hooks - tryFinalizeTransition(match, key) + handleRouteEntered(match, key) }) } next(cb) diff --git a/src/util/route.js b/src/util/route.js index 79d8fcee5..84bb10c45 100644 --- a/src/util/route.js +++ b/src/util/route.js @@ -131,11 +131,11 @@ function queryIncludes (current: Dictionary, target: Dictionary) return true } -export function tryFinalizeTransition (record: RouteRecord, name: string) { - if (record.instances[name] && record.pendingCbs[name]) { +export function handleRouteEntered (record: RouteRecord, name: string) { + if (record.instances[name] && record.enteredCbs[name]) { const instance = record.instances[name] - const cbs = record.pendingCbs[name] - delete record.pendingCbs[name] + const cbs = record.enteredCbs[name] + delete record.enteredCbs[name] for (let i = 0; i < cbs.length; i++) { cbs[i](instance) } From 429a38c6af785cfe5bbf1665bf7d77253842ea9c Mon Sep 17 00:00:00 2001 From: Ronald Rogers Date: Thu, 8 Aug 2019 00:47:42 -0400 Subject: [PATCH 04/10] fix: fixed bug from refactoring --- src/create-route-map.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/create-route-map.js b/src/create-route-map.js index 6d9608fbb..232e25e66 100644 --- a/src/create-route-map.js +++ b/src/create-route-map.js @@ -73,7 +73,7 @@ function addRouteRecord ( regex: compileRouteRegex(normalizedPath, pathToRegexpOptions), components: route.components || { default: route.component }, instances: {}, - pendingCbs: {}, + enteredCbs: {}, name, parent, matchAs, From aff081e712f98b605ea85aedc0e49968c35870e1 Mon Sep 17 00:00:00 2001 From: Ronald Rogers Date: Thu, 8 Aug 2019 01:23:36 -0400 Subject: [PATCH 05/10] refactor: a little bit more refactoring --- src/components/view.js | 12 ++++++------ src/history/base.js | 4 +++- src/util/route.js | 13 ++++++------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/components/view.js b/src/components/view.js index e64be5156..d5c71d5c9 100644 --- a/src/components/view.js +++ b/src/components/view.js @@ -71,11 +71,6 @@ export default { // in case the same component instance is reused across different routes ;(data.hook || (data.hook = {})).prepatch = (_, vnode) => { matched.instances[name] = vnode.componentInstance - // if the route transition has already been confirmed then we weren't - // able to call the cb during confirmation as the component was not - // registered yet, so we call it here. - matched.enteredCbs - handleRouteEntered(matched, name) } // register instance in init hook @@ -86,7 +81,12 @@ export default { vnode.componentInstance !== matched.instances[name] ) { matched.instances[name] = vnode.componentInstance - handleRouteEntered(matched, name) + // if the route transition has already been confirmed then we weren't + // able to call the cbs during confirmation as the component was not + // registered yet, so we call it here. + if (matched.enteredCbs[name]) { + handleRouteEntered(matched, name) + } } } diff --git a/src/history/base.js b/src/history/base.js index 9072ceeba..c0bd8fcc4 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -324,7 +324,9 @@ function bindEnterGuard ( cbs.push(() => { // if the instance is registered call the cb here, otherwise it will // get called when it is registered in the component's lifecycle hooks - handleRouteEntered(match, key) + if (match.instances[key]) { + handleRouteEntered(match, key) + } }) } next(cb) diff --git a/src/util/route.js b/src/util/route.js index 84bb10c45..5d4c7ad18 100644 --- a/src/util/route.js +++ b/src/util/route.js @@ -132,12 +132,11 @@ function queryIncludes (current: Dictionary, target: Dictionary) } export function handleRouteEntered (record: RouteRecord, name: string) { - if (record.instances[name] && record.enteredCbs[name]) { - const instance = record.instances[name] - const cbs = record.enteredCbs[name] - delete record.enteredCbs[name] - for (let i = 0; i < cbs.length; i++) { - cbs[i](instance) - } + const instance = record.instances[name] + const cbs = record.enteredCbs[name] + if (!instance || !cbs) return + delete record.enteredCbs[name] + for (let i = 0; i < cbs.length; i++) { + cbs[i](instance) } } From ecd71e7df5ffaeef9a134e710e75c34b0936876c Mon Sep 17 00:00:00 2001 From: Ronald Rogers Date: Fri, 9 Aug 2019 00:02:46 -0400 Subject: [PATCH 06/10] fix: fixed enter cb not called in out-in transitions still --- src/components/view.js | 11 +++++------ src/history/base.js | 22 +++++----------------- src/util/route.js | 19 ++++++++++++------- 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/src/components/view.js b/src/components/view.js index d5c71d5c9..53b0495f6 100644 --- a/src/components/view.js +++ b/src/components/view.js @@ -81,13 +81,12 @@ export default { vnode.componentInstance !== matched.instances[name] ) { matched.instances[name] = vnode.componentInstance - // if the route transition has already been confirmed then we weren't - // able to call the cbs during confirmation as the component was not - // registered yet, so we call it here. - if (matched.enteredCbs[name]) { - handleRouteEntered(matched, name) - } } + + // if the route transition has already been confirmed then we weren't + // able to call the cbs during confirmation as the component was not + // registered yet, so we call it here. + handleRouteEntered(route) } // resolve props diff --git a/src/history/base.js b/src/history/base.js index c0bd8fcc4..b8a8eeb29 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -177,10 +177,9 @@ export class History { } runQueue(queue, iterator, () => { - const enteredCbs = [] // wait until async components are resolved before // extracting in-component enter guards - const enterGuards = extractEnterGuards(activated, enteredCbs) + const enterGuards = extractEnterGuards(activated) const queue = enterGuards.concat(this.router.resolveHooks) runQueue(queue, iterator, () => { if (this.pending !== route) { @@ -190,9 +189,7 @@ export class History { onComplete(route) if (this.router.app) { this.router.app.$nextTick(() => { - enteredCbs.forEach(cb => { - cb() - }) + handleRouteEntered(route) }) } }) @@ -296,14 +293,13 @@ function bindGuard (guard: NavigationGuard, instance: ?_Vue): ?NavigationGuard { } function extractEnterGuards ( - activated: Array, - cbs: Array, + activated: Array ): Array { return extractGuards( activated, 'beforeRouteEnter', (guard, _, match, key) => { - return bindEnterGuard(guard, match, key, cbs) + return bindEnterGuard(guard, match, key) } ) } @@ -311,8 +307,7 @@ function extractEnterGuards ( function bindEnterGuard ( guard: NavigationGuard, match: RouteRecord, - key: string, - cbs: Array, + key: string ): NavigationGuard { return function routeEnterGuard (to, from, next) { return guard(to, from, cb => { @@ -321,13 +316,6 @@ function bindEnterGuard ( match.enteredCbs[key] = [] } match.enteredCbs[key].push(cb) - cbs.push(() => { - // if the instance is registered call the cb here, otherwise it will - // get called when it is registered in the component's lifecycle hooks - if (match.instances[key]) { - handleRouteEntered(match, key) - } - }) } next(cb) }) diff --git a/src/util/route.js b/src/util/route.js index 5d4c7ad18..609721ee0 100644 --- a/src/util/route.js +++ b/src/util/route.js @@ -131,12 +131,17 @@ function queryIncludes (current: Dictionary, target: Dictionary) return true } -export function handleRouteEntered (record: RouteRecord, name: string) { - const instance = record.instances[name] - const cbs = record.enteredCbs[name] - if (!instance || !cbs) return - delete record.enteredCbs[name] - for (let i = 0; i < cbs.length; i++) { - cbs[i](instance) +export function handleRouteEntered (route: Route) { + for (let i = 0; i < route.matched.length; i++) { + const record = route.matched[i] + for (const name in record.instances) { + const instance = record.instances[name] + const cbs = record.enteredCbs[name] + if (!instance || !cbs) continue + delete record.enteredCbs[name] + for (let i = 0; i < cbs.length; i++) { + cbs[i](instance) + } + } } } From f340981a4c943639dc30be0cd10e530801b8eebf Mon Sep 17 00:00:00 2001 From: Ronald Rogers Date: Sat, 10 Aug 2019 14:02:52 -0400 Subject: [PATCH 07/10] chore(test): added coverage for out-in transition before route enter cb --- examples/navigation-guards/app.js | 47 +++++++++++++++++++-------- examples/navigation-guards/index.html | 8 +++++ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/examples/navigation-guards/app.js b/examples/navigation-guards/app.js index 86b2c9496..85c4af416 100644 --- a/examples/navigation-guards/app.js +++ b/examples/navigation-guards/app.js @@ -91,15 +91,25 @@ const Quux = { } const NestedParent = { - template: `
Nested Parent
- /parent/child/1 - /parent/child/2 -
-

- {{ log }} -

- -
`, + template: ` +
+ Nested Parent +
+ /parent/child/1 + /parent/child/2 +
+

+ {{ log }} +

+ + + + + + + + +
`, data: () => ({ logs: [] }), beforeRouteEnter (to, from, next) { next(vm => { @@ -116,7 +126,18 @@ const GuardMixin = { } } -const NestedChild = { +const NestedChild1 = { + props: ['n'], + template: `
Child {{ n }}
`, + mixins: [GuardMixin], + beforeRouteEnter (to, from, next) { + next(vm => { + vm.$parent.logs.push('child ' + vm.n) + }) + } +} + +const NestedChild2 = { props: ['n'], template: `
Child {{ n }}
`, mixins: [GuardMixin], @@ -162,10 +183,10 @@ const router = new VueRouter({ path: '/parent', component: NestedParent, children: [ - { path: 'child/1', component: NestedChild, props: { n: 1 }}, - { path: 'child/2', component: NestedChild, props: { n: 2 }} + { path: 'child/1', component: NestedChild1, props: { n: 1 }}, + { path: 'child/2', component: NestedChild2, props: { n: 2 }} ] - } + }, ] }) diff --git a/examples/navigation-guards/index.html b/examples/navigation-guards/index.html index 0e7e950ee..580cb9768 100644 --- a/examples/navigation-guards/index.html +++ b/examples/navigation-guards/index.html @@ -1,5 +1,13 @@ + ← Examples index
From 493ec4759a84831be1ce35e0856155e4f5df1249 Mon Sep 17 00:00:00 2001 From: Ronald Rogers Date: Sat, 10 Aug 2019 14:20:53 -0400 Subject: [PATCH 08/10] fix: lint --- examples/navigation-guards/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/navigation-guards/app.js b/examples/navigation-guards/app.js index 85c4af416..62e526503 100644 --- a/examples/navigation-guards/app.js +++ b/examples/navigation-guards/app.js @@ -186,7 +186,7 @@ const router = new VueRouter({ { path: 'child/1', component: NestedChild1, props: { n: 1 }}, { path: 'child/2', component: NestedChild2, props: { n: 2 }} ] - }, + } ] }) From 84b74ec594c7c31a8becbf52a71a424a4a6190ad Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Mon, 23 Sep 2019 12:10:58 +0200 Subject: [PATCH 09/10] refactor: use one single component --- examples/navigation-guards/app.js | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/examples/navigation-guards/app.js b/examples/navigation-guards/app.js index 62e526503..48de8aa0d 100644 --- a/examples/navigation-guards/app.js +++ b/examples/navigation-guards/app.js @@ -107,7 +107,7 @@ const NestedParent = { - + `, data: () => ({ logs: [] }), @@ -126,18 +126,7 @@ const GuardMixin = { } } -const NestedChild1 = { - props: ['n'], - template: `
Child {{ n }}
`, - mixins: [GuardMixin], - beforeRouteEnter (to, from, next) { - next(vm => { - vm.$parent.logs.push('child ' + vm.n) - }) - } -} - -const NestedChild2 = { +const NestedChild = { props: ['n'], template: `
Child {{ n }}
`, mixins: [GuardMixin], @@ -183,8 +172,8 @@ const router = new VueRouter({ path: '/parent', component: NestedParent, children: [ - { path: 'child/1', component: NestedChild1, props: { n: 1 }}, - { path: 'child/2', component: NestedChild2, props: { n: 2 }} + { path: 'child/1', component: NestedChild, props: { n: 1 }}, + { path: 'child/2', component: NestedChild, props: { n: 2 }} ] } ] From 0c8f65aa8fb5cff443bf700642898690fc11eac6 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Tue, 24 Sep 2019 10:00:30 +0200 Subject: [PATCH 10/10] refactor: add back the isBeingDestroyed check --- src/util/route.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/route.js b/src/util/route.js index 609721ee0..2a15419e0 100644 --- a/src/util/route.js +++ b/src/util/route.js @@ -140,7 +140,7 @@ export function handleRouteEntered (route: Route) { if (!instance || !cbs) continue delete record.enteredCbs[name] for (let i = 0; i < cbs.length; i++) { - cbs[i](instance) + if (!instance._isBeingDestroyed) cbs[i](instance) } } }