diff --git a/examples/navigation-guards/app.js b/examples/navigation-guards/app.js
index 86b2c9496..48de8aa0d 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 => {
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
diff --git a/flow/declarations.js b/flow/declarations.js
index 942aa73bf..ee1a10283 100644
--- a/flow/declarations.js
+++ b/flow/declarations.js
@@ -68,6 +68,7 @@ declare type RouteRecord = {
regex: RouteRegExp;
components: Dictionary;
instances: Dictionary;
+ enteredCbs: Dictionary>;
name: ?string;
parent: ?RouteRecord;
redirect: ?RedirectOption;
diff --git a/src/components/view.js b/src/components/view.js
index de764fdf5..442e9a69e 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 { handleRouteEntered } from '../util/route'
export default {
name: 'RouterView',
@@ -94,6 +95,11 @@ export default {
) {
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.
+ handleRouteEntered(route)
}
const configProps = matched.props && matched.props[name]
diff --git a/src/create-route-map.js b/src/create-route-map.js
index aa51864a9..c05896845 100644
--- a/src/create-route-map.js
+++ b/src/create-route-map.js
@@ -85,6 +85,7 @@ function addRouteRecord (
regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),
components: route.components || { default: route.component },
instances: {},
+ enteredCbs: {},
name,
parent,
matchAs,
diff --git a/src/history/base.js b/src/history/base.js
index 05a5652f9..5f2bad870 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 } from '../util/warn'
-import { START, isSameRoute } from '../util/route'
+import { START, isSameRoute, handleRouteEntered } from '../util/route'
import {
flatten,
flatMapComponents,
@@ -218,11 +218,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)
const queue = enterGuards.concat(this.router.resolveHooks)
runQueue(queue, iterator, () => {
if (this.pending !== route) {
@@ -232,9 +230,7 @@ export class History {
onComplete(route)
if (this.router.app) {
this.router.app.$nextTick(() => {
- postEnterCbs.forEach(cb => {
- cb()
- })
+ handleRouteEntered(route)
})
}
})
@@ -352,15 +348,13 @@ function bindGuard (guard: NavigationGuard, instance: ?_Vue): ?NavigationGuard {
}
function extractEnterGuards (
- activated: Array,
- cbs: Array,
- isValid: () => boolean
+ activated: Array
): Array {
return extractGuards(
activated,
'beforeRouteEnter',
(guard, _, match, key) => {
- return bindEnterGuard(guard, match, key, cbs, isValid)
+ return bindEnterGuard(guard, match, key)
}
)
}
@@ -368,41 +362,17 @@ function extractEnterGuards (
function bindEnterGuard (
guard: NavigationGuard,
match: RouteRecord,
- key: string,
- cbs: Array,
- isValid: () => boolean
+ key: string
): NavigationGuard {
return function routeEnterGuard (to, from, next) {
return guard(to, from, cb => {
if (typeof cb === 'function') {
- 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 (!match.enteredCbs[key]) {
+ match.enteredCbs[key] = []
+ }
+ match.enteredCbs[key].push(cb)
}
next(cb)
})
}
}
-
-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)
- }
-}
diff --git a/src/util/route.js b/src/util/route.js
index 6b049ccc2..268488ac0 100644
--- a/src/util/route.js
+++ b/src/util/route.js
@@ -132,3 +132,18 @@ function queryIncludes (current: Dictionary, target: Dictionary)
}
return true
}
+
+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++) {
+ if (!instance._isBeingDestroyed) cbs[i](instance)
+ }
+ }
+ }
+}