feat(nuxt): add onBeforeRouteLeave and onBeforeRouteUpdate composables (#8889)

This commit is contained in:
Daniel Roe 2022-11-10 14:52:04 +01:00 committed by GitHub
parent 3e34a61506
commit e6351349c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 8 deletions

View File

@ -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'

View File

@ -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'
@ -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

View File

@ -31,23 +31,26 @@ export default defineNuxtModule<Partial<ImportsOptions>>({
options = defu(nuxt.options.autoImports, options)
}
// Allow modules extending sources
await nuxt.callHook('imports:sources', options.presets as ImportPresetWithDeprecation[])
// TODO: fix sharing of defaults between invocations of modules
const presets = JSON.parse(JSON.stringify(options.presets)) as ImportPresetWithDeprecation[]
options.presets?.forEach((_i) => {
// Allow modules extending sources
await nuxt.callHook('imports:sources', presets)
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: {

View File

@ -64,6 +64,15 @@ const appPreset = defineUnimportPreset({
]
})
// vue-router
const routerPreset = defineUnimportPreset({
from: '#app',
imports: [
'onBeforeRouteLeave',
'onBeforeRouteUpdate'
]
})
// vue
const vuePreset = defineUnimportPreset({
from: 'vue',
@ -140,5 +149,6 @@ const vuePreset = defineUnimportPreset({
export const defaultPresets: InlinePreset[] = [
...commonPresets,
appPreset,
routerPreset,
vuePreset
]

View File

@ -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 = [

View File

@ -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) {