mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-31 07:40:33 +00:00
fix(nuxt): use route key for loading indicator/view transition (#23868)
This commit is contained in:
parent
a13bf67ecb
commit
df022a4a9d
@ -1,4 +1,5 @@
|
|||||||
import { computed, defineComponent, h, onBeforeUnmount, ref } from 'vue'
|
import { computed, defineComponent, h, onBeforeUnmount, ref } from 'vue'
|
||||||
|
import { isChangingPage } from './utils'
|
||||||
import { useNuxtApp } from '#app/nuxt'
|
import { useNuxtApp } from '#app/nuxt'
|
||||||
import { useRouter } from '#app/composables/router'
|
import { useRouter } from '#app/composables/router'
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ export default defineComponent({
|
|||||||
indicator.finish()
|
indicator.finish()
|
||||||
})
|
})
|
||||||
router.beforeResolve((to, from) => {
|
router.beforeResolve((to, from) => {
|
||||||
if (to === from || to.matched.every((comp, index) => comp.components && comp.components?.default === from.matched[index]?.components?.default)) {
|
if (!isChangingPage(to, from)) {
|
||||||
indicator.finish()
|
indicator.finish()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -3,6 +3,7 @@ import type { Component, RendererNode } from 'vue'
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
import { isString, isPromise, isArray, isObject } from '@vue/shared'
|
import { isString, isPromise, isArray, isObject } from '@vue/shared'
|
||||||
import destr from 'destr'
|
import destr from 'destr'
|
||||||
|
import type { RouteLocationNormalized } from '#vue-router'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal utility
|
* Internal utility
|
||||||
@ -13,6 +14,35 @@ export const _wrapIf = (component: Component, props: any, slots: any) => {
|
|||||||
return { default: () => props ? h(component, props, slots) : slots.default?.() }
|
return { default: () => props ? h(component, props, slots) : slots.default?.() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: consider refactoring into single utility
|
||||||
|
// See https://github.com/nuxt/nuxt/tree/main/packages/nuxt/src/pages/runtime/utils.ts#L8-L19
|
||||||
|
function generateRouteKey (route: RouteLocationNormalized) {
|
||||||
|
const source = route?.meta.key ?? route.path
|
||||||
|
.replace(/(:\w+)\([^)]+\)/g, '$1')
|
||||||
|
.replace(/(:\w+)[?+*]/g, '$1')
|
||||||
|
.replace(/:\w+/g, r => route.params[r.slice(1)]?.toString() || '')
|
||||||
|
return typeof source === 'function' ? source(route) : source
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility used within router guards
|
||||||
|
* return true if the route has been changed with a page change during navigation
|
||||||
|
*/
|
||||||
|
export function isChangingPage (to: RouteLocationNormalized, from: RouteLocationNormalized) {
|
||||||
|
if (to === from) { return false }
|
||||||
|
|
||||||
|
// If route keys are different then it will result in a rerender
|
||||||
|
if (generateRouteKey(to) !== generateRouteKey(from)) { return true }
|
||||||
|
|
||||||
|
const areComponentsSame = to.matched.every((comp, index) =>
|
||||||
|
comp.components && comp.components.default === from.matched[index]?.components?.default
|
||||||
|
)
|
||||||
|
if (areComponentsSame) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-use-before-define
|
// eslint-disable-next-line no-use-before-define
|
||||||
export type SSRBuffer = SSRBufferItem[] & { hasAsync?: boolean }
|
export type SSRBuffer = SSRBufferItem[] & { hasAsync?: boolean }
|
||||||
export type SSRBufferItem = string | SSRBuffer | Promise<SSRBuffer>
|
export type SSRBufferItem = string | SSRBuffer | Promise<SSRBuffer>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { isChangingPage } from '#app/components/utils'
|
||||||
import { useRouter } from '#app/composables/router'
|
import { useRouter } from '#app/composables/router'
|
||||||
import { defineNuxtPlugin } from '#app/nuxt'
|
import { defineNuxtPlugin } from '#app/nuxt'
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
router.beforeResolve((to, from) => {
|
router.beforeResolve((to, from) => {
|
||||||
if (to === from || to.matched.every((comp, index) => comp.components && comp.components?.default === from.matched[index]?.components?.default)) {
|
if (!isChangingPage(to, from)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const promise = new Promise<void>((resolve, reject) => {
|
const promise = new Promise<void>((resolve, reject) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user