mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 23:22:02 +00:00
feat(nuxt): add onBeforeRouteLeave
and onBeforeRouteUpdate
composables (#8889)
This commit is contained in:
parent
3e34a61506
commit
e6351349c0
@ -10,7 +10,7 @@ export type { FetchResult, UseFetchOptions } from './fetch'
|
|||||||
export { useCookie } from './cookie'
|
export { useCookie } from './cookie'
|
||||||
export type { CookieOptions, CookieRef } from './cookie'
|
export type { CookieOptions, CookieRef } from './cookie'
|
||||||
export { useRequestHeaders, useRequestEvent, setResponseStatus } from './ssr'
|
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 type { AddRouteMiddlewareOptions, RouteMiddleware } from './router'
|
||||||
export { preloadComponents, prefetchComponents, preloadRouteComponents } from './preload'
|
export { preloadComponents, prefetchComponents, preloadRouteComponents } from './preload'
|
||||||
export { isPrerendered, loadPayload, preloadPayload } from './payload'
|
export { isPrerendered, loadPayload, preloadPayload } from './payload'
|
||||||
|
@ -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 type { Router, RouteLocationNormalizedLoaded, NavigationGuard, RouteLocationNormalized, RouteLocationRaw, NavigationFailure, RouteLocationPathRaw } from 'vue-router'
|
||||||
import { sendRedirect } from 'h3'
|
import { sendRedirect } from 'h3'
|
||||||
import { hasProtocol, joinURL, parseURL } from 'ufo'
|
import { hasProtocol, joinURL, parseURL } from 'ufo'
|
||||||
@ -17,6 +17,19 @@ export const useRoute = (): RouteLocationNormalizedLoaded => {
|
|||||||
return useNuxtApp()._route
|
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. */
|
/** @deprecated Use `useRoute` instead. */
|
||||||
export const useActiveRoute = (): RouteLocationNormalizedLoaded => {
|
export const useActiveRoute = (): RouteLocationNormalizedLoaded => {
|
||||||
return useNuxtApp()._route
|
return useNuxtApp()._route
|
||||||
|
@ -31,23 +31,26 @@ export default defineNuxtModule<Partial<ImportsOptions>>({
|
|||||||
options = defu(nuxt.options.autoImports, options)
|
options = defu(nuxt.options.autoImports, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow modules extending sources
|
// TODO: fix sharing of defaults between invocations of modules
|
||||||
await nuxt.callHook('imports:sources', options.presets as ImportPresetWithDeprecation[])
|
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
|
const i = _i as ImportPresetWithDeprecation | string
|
||||||
if (typeof i !== 'string' && i.names && !i.imports) {
|
if (typeof i !== 'string' && i.names && !i.imports) {
|
||||||
i.imports = i.names
|
i.imports = i.names
|
||||||
logger.warn('imports: presets.names is deprecated, use presets.imports instead')
|
logger.warn('imports: presets.names is deprecated, use presets.imports instead')
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
// Filter disabled sources
|
// Filter disabled sources
|
||||||
// options.sources = options.sources.filter(source => source.disabled !== true)
|
// options.sources = options.sources.filter(source => source.disabled !== true)
|
||||||
|
|
||||||
// Create a context to share state between module internals
|
// Create a context to share state between module internals
|
||||||
const ctx = createUnimport({
|
const ctx = createUnimport({
|
||||||
presets: options.presets,
|
presets,
|
||||||
imports: options.imports,
|
imports: options.imports,
|
||||||
virtualImports: ['#imports'],
|
virtualImports: ['#imports'],
|
||||||
addons: {
|
addons: {
|
||||||
|
@ -64,6 +64,15 @@ const appPreset = defineUnimportPreset({
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// vue-router
|
||||||
|
const routerPreset = defineUnimportPreset({
|
||||||
|
from: '#app',
|
||||||
|
imports: [
|
||||||
|
'onBeforeRouteLeave',
|
||||||
|
'onBeforeRouteUpdate'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
// vue
|
// vue
|
||||||
const vuePreset = defineUnimportPreset({
|
const vuePreset = defineUnimportPreset({
|
||||||
from: 'vue',
|
from: 'vue',
|
||||||
@ -140,5 +149,6 @@ const vuePreset = defineUnimportPreset({
|
|||||||
export const defaultPresets: InlinePreset[] = [
|
export const defaultPresets: InlinePreset[] = [
|
||||||
...commonPresets,
|
...commonPresets,
|
||||||
appPreset,
|
appPreset,
|
||||||
|
routerPreset,
|
||||||
vuePreset
|
vuePreset
|
||||||
]
|
]
|
||||||
|
@ -54,6 +54,14 @@ export default defineNuxtModule({
|
|||||||
references.push({ types: 'vue-router' })
|
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
|
// Regenerate templates when adding or removing pages
|
||||||
nuxt.hook('builder:watch', async (event, path) => {
|
nuxt.hook('builder:watch', async (event, path) => {
|
||||||
const dirs = [
|
const dirs = [
|
||||||
|
@ -66,7 +66,7 @@ describe('imports:nuxt', () => {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
it(`should register ${name} globally`, () => {
|
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) {
|
} catch (e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user