diff --git a/packages/router/__tests__/guards/navigatioGuardsInjections.spec.ts b/packages/router/__tests__/guards/navigatioGuardsInjections.spec.ts
index a660b1c12..fe20236be 100644
--- a/packages/router/__tests__/guards/navigatioGuardsInjections.spec.ts
+++ b/packages/router/__tests__/guards/navigatioGuardsInjections.spec.ts
@@ -48,4 +48,92 @@ describe('inject() within navigation guards', () => {
await router.isReady()
})
}
+
+ describe('in-component guards', () => {
+ it('beforeRouteEnter', async () => {
+ expect.assertions(1)
+ const router = createRouter({
+ routes: [
+ {
+ path: '/',
+ component: {
+ template: `
Page
`,
+ beforeRouteEnter() {
+ expect(inject('test')).toBe('hello')
+ },
+ },
+ },
+ ],
+ })
+ factory(router)
+ await router.isReady()
+ await router.push('/')
+ })
+
+ it('beforeRouteEnter + lazy load', async () => {
+ expect.assertions(1)
+ const router = createRouter({
+ routes: [
+ {
+ path: '/',
+ component: () =>
+ new Promise(r =>
+ r({
+ template: `Page
`,
+ beforeRouteEnter() {
+ expect(inject('test')).toBe('hello')
+ },
+ })
+ ),
+ },
+ ],
+ })
+ factory(router)
+ await router.isReady()
+ await router.push('/')
+ })
+
+ it('beforeRouteUpdate', async () => {
+ expect.assertions(1)
+ const router = createRouter({
+ routes: [
+ {
+ path: '/',
+ component: {
+ template: `Page
`,
+ beforeRouteUpdate() {
+ expect(inject('test')).toBe('hello')
+ },
+ },
+ },
+ ],
+ })
+ factory(router)
+ await router.isReady()
+ await router.push('/')
+ await router.push('/#other')
+ })
+
+ it('beforeRouteLeave', async () => {
+ expect.assertions(1)
+ const router = createRouter({
+ routes: [
+ { path: '/', component: PageComponent },
+ {
+ path: '/foo',
+ component: {
+ template: `Page
`,
+ beforeRouteLeave() {
+ expect(inject('test')).toBe('hello')
+ },
+ },
+ },
+ ],
+ })
+ factory(router)
+ await router.isReady()
+ await router.push('/foo')
+ await router.push('/')
+ })
+ })
})
diff --git a/packages/router/src/navigationGuards.ts b/packages/router/src/navigationGuards.ts
index 148a51f27..27eac6cfc 100644
--- a/packages/router/src/navigationGuards.ts
+++ b/packages/router/src/navigationGuards.ts
@@ -117,14 +117,16 @@ export function guardToPromiseFn(
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded,
record: RouteRecordNormalized,
- name: string
+ name: string,
+ runWithContext: (fn: () => T) => T
): () => Promise
export function guardToPromiseFn(
guard: NavigationGuard,
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded,
record?: RouteRecordNormalized,
- name?: string
+ name?: string,
+ runWithContext: (fn: () => T) => T = fn => fn()
): () => Promise {
// keep a reference to the enterCallbackArray to prevent pushing callbacks if a new navigation took place
const enterCallbackArray =
@@ -173,11 +175,13 @@ export function guardToPromiseFn(
}
// wrapping with Promise.resolve allows it to work with both async and sync guards
- const guardReturn = guard.call(
- record && record.instances[name!],
- to,
- from,
- __DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
+ const guardReturn = runWithContext(() =>
+ guard.call(
+ record && record.instances[name!],
+ to,
+ from,
+ __DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
+ )
)
let guardCall = Promise.resolve(guardReturn)
@@ -231,7 +235,8 @@ export function extractComponentsGuards(
matched: RouteRecordNormalized[],
guardType: GuardType,
to: RouteLocationNormalized,
- from: RouteLocationNormalizedLoaded
+ from: RouteLocationNormalizedLoaded,
+ runWithContext: (fn: () => T) => T = fn => fn()
) {
const guards: Array<() => Promise> = []
@@ -292,7 +297,10 @@ export function extractComponentsGuards(
const options: ComponentOptions =
(rawComponent as any).__vccOpts || rawComponent
const guard = options[guardType]
- guard && guards.push(guardToPromiseFn(guard, to, from, record, name))
+ guard &&
+ guards.push(
+ guardToPromiseFn(guard, to, from, record, name, runWithContext)
+ )
} else {
// start requesting the chunk already
let componentPromise: Promise<
@@ -324,7 +332,10 @@ export function extractComponentsGuards(
const options: ComponentOptions =
(resolvedComponent as any).__vccOpts || resolvedComponent
const guard = options[guardType]
- return guard && guardToPromiseFn(guard, to, from, record, name)()
+ return (
+ guard &&
+ guardToPromiseFn(guard, to, from, record, name, runWithContext)()
+ )
})
)
}
diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts
index f5cc271ee..b1ec39dfd 100644
--- a/packages/router/src/router.ts
+++ b/packages/router/src/router.ts
@@ -879,7 +879,8 @@ export function createRouter(options: RouterOptions): Router {
enteringRecords,
'beforeRouteEnter',
to,
- from
+ from,
+ runWithContext
)
guards.push(canceledNavigationCheck)