Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

Commit

Permalink
feat(nuxt): add onBeforeRouteLeave and onBeforeRouteUpdate compos…
Browse files Browse the repository at this point in the history
…ables (#8889)
  • Loading branch information
danielroe authored Nov 10, 2022
1 parent 3e34a61 commit e635134
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/composables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type { FetchResult, UseFetchOptions } from './fetch'
export { useCookie } from './cookie'
export type { CookieOptions, CookieRef } from './cookie'
export { useRequestHeaders, useRequestEvent, setResponseStatus } from './ssr'
export { abortNavigation, addRouteMiddleware, defineNuxtRouteMiddleware, setPageLayout, navigateTo, useRoute, useActiveRoute, useRouter } from './router'
export { abortNavigation, addRouteMiddleware, defineNuxtRouteMiddleware, onBeforeRouteLeave, onBeforeRouteUpdate, setPageLayout, navigateTo, useRoute, useActiveRoute, useRouter } from './router'
export type { AddRouteMiddlewareOptions, RouteMiddleware } from './router'
export { preloadComponents, prefetchComponents, preloadRouteComponents } from './preload'
export { isPrerendered, loadPayload, preloadPayload } from './payload'
15 changes: 14 additions & 1 deletion packages/nuxt/src/app/composables/router.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCurrentInstance, inject } from 'vue'
import { getCurrentInstance, inject, onUnmounted } from 'vue'
import type { Router, RouteLocationNormalizedLoaded, NavigationGuard, RouteLocationNormalized, RouteLocationRaw, NavigationFailure, RouteLocationPathRaw } from 'vue-router'
import { sendRedirect } from 'h3'
import { hasProtocol, joinURL, parseURL } from 'ufo'
Expand All @@ -17,6 +17,19 @@ export const useRoute = (): RouteLocationNormalizedLoaded => {
return useNuxtApp()._route
}

export const onBeforeRouteLeave = (guard: NavigationGuard) => {
const unsubscribe = useRouter().beforeEach((to, from, next) => {
if (to === from) { return }
return guard(to, from, next)
})
onUnmounted(unsubscribe)
}

export const onBeforeRouteUpdate = (guard: NavigationGuard) => {
const unsubscribe = useRouter().beforeEach(guard)
onUnmounted(unsubscribe)
}

/** @deprecated Use `useRoute` instead. */
export const useActiveRoute = (): RouteLocationNormalizedLoaded => {
return useNuxtApp()._route
Expand Down
11 changes: 7 additions & 4 deletions packages/nuxt/src/imports/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,26 @@ export default defineNuxtModule<Partial<ImportsOptions>>({
options = defu(nuxt.options.autoImports, options)
}

// TODO: fix sharing of defaults between invocations of modules
const presets = JSON.parse(JSON.stringify(options.presets)) as ImportPresetWithDeprecation[]

// Allow modules extending sources
await nuxt.callHook('imports:sources', options.presets as ImportPresetWithDeprecation[])
await nuxt.callHook('imports:sources', presets)

options.presets?.forEach((_i) => {
for (const _i of presets) {
const i = _i as ImportPresetWithDeprecation | string
if (typeof i !== 'string' && i.names && !i.imports) {
i.imports = i.names
logger.warn('imports: presets.names is deprecated, use presets.imports instead')
}
})
}

// Filter disabled sources
// options.sources = options.sources.filter(source => source.disabled !== true)

// Create a context to share state between module internals
const ctx = createUnimport({
presets: options.presets,
presets,
imports: options.imports,
virtualImports: ['#imports'],
addons: {
Expand Down
10 changes: 10 additions & 0 deletions packages/nuxt/src/imports/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ const appPreset = defineUnimportPreset({
]
})

// vue-router
const routerPreset = defineUnimportPreset({
from: '#app',
imports: [
'onBeforeRouteLeave',
'onBeforeRouteUpdate'
]
})

// vue
const vuePreset = defineUnimportPreset({
from: 'vue',
Expand Down Expand Up @@ -140,5 +149,6 @@ const vuePreset = defineUnimportPreset({
export const defaultPresets: InlinePreset[] = [
...commonPresets,
appPreset,
routerPreset,
vuePreset
]
8 changes: 8 additions & 0 deletions packages/nuxt/src/pages/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ export default defineNuxtModule({
references.push({ types: 'vue-router' })
})

// Add vue-router route guard imports
nuxt.hook('imports:sources', (sources) => {
const routerImports = sources.find(s => s.from === '#app' && s.imports.includes('onBeforeRouteLeave'))
if (routerImports) {
routerImports.from = 'vue-router'
}
})

// Regenerate templates when adding or removing pages
nuxt.hook('builder:watch', async (event, path) => {
const dirs = [
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/test/auto-imports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe('imports:nuxt', () => {
continue
}
it(`should register ${name} globally`, () => {
expect(defaultPresets.find(a => a.from === '#app')!.imports).to.include(name)
expect(defaultPresets.flatMap(a => a.from === '#app' ? a.imports : [])).to.include(name)
})
}
} catch (e) {
Expand Down

0 comments on commit e635134

Please sign in to comment.