mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
fix(vue-app): prevent mounting page twice on redirect (#5361)
This commit is contained in:
parent
7ce30935fa
commit
2d73e8aeba
@ -649,6 +649,10 @@ async function mountApp(__app) {
|
||||
const mount = () => {
|
||||
_app.$mount('#<%= globals.id %>')
|
||||
|
||||
// Add afterEach router hooks
|
||||
router.afterEach(normalizeComponents)
|
||||
router.afterEach(fixPrepatch.bind(_app))
|
||||
|
||||
// Listen for first Vue update
|
||||
Vue.nextTick(() => {
|
||||
// Call window.{{globals.readyCallback}} callbacks
|
||||
@ -671,11 +675,9 @@ async function mountApp(__app) {
|
||||
_app.$loading = {} // To avoid error while _app.$nuxt does not exist
|
||||
if (NUXT.error) _app.error(NUXT.error)
|
||||
|
||||
// Add router hooks
|
||||
// Add beforeEach router hooks
|
||||
router.beforeEach(loadAsyncComponents.bind(_app))
|
||||
router.beforeEach(render.bind(_app))
|
||||
router.afterEach(normalizeComponents)
|
||||
router.afterEach(fixPrepatch.bind(_app))
|
||||
|
||||
// If page already is server rendered
|
||||
if (NUXT.serverRendered) {
|
||||
@ -684,20 +686,30 @@ async function mountApp(__app) {
|
||||
}
|
||||
|
||||
// First render on client-side
|
||||
const clientFirstMount = () => {
|
||||
normalizeComponents(router.currentRoute, router.currentRoute)
|
||||
showNextPage.call(_app, router.currentRoute)
|
||||
// Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
|
||||
mount()
|
||||
}
|
||||
|
||||
render.call(_app, router.currentRoute, router.currentRoute, (path) => {
|
||||
// If not redirected
|
||||
if (!path) {
|
||||
normalizeComponents(router.currentRoute, router.currentRoute)
|
||||
showNextPage.call(_app, router.currentRoute)
|
||||
// Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
|
||||
mount()
|
||||
clientFirstMount()
|
||||
return
|
||||
}
|
||||
|
||||
// Push the path and then mount app
|
||||
router.push(path, () => mount(), (err) => {
|
||||
if (!err) return mount()
|
||||
errorHandler(err)
|
||||
// Add a one-time afterEach hook to
|
||||
// mount the app wait for redirect and route gets resolved
|
||||
const unregisterHook = router.afterEach((to, from) => {
|
||||
unregisterHook()
|
||||
clientFirstMount()
|
||||
})
|
||||
|
||||
// Push the path and let route to be resolved
|
||||
router.push(path, undefined, (err) => {
|
||||
if (err) errorHandler(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
14
test/fixtures/spa/middleware/middleware.js
vendored
Normal file
14
test/fixtures/spa/middleware/middleware.js
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
export default function ({ route, redirect }) {
|
||||
const redirectPathRegexp = /^\/redirect(\d+)$/
|
||||
const match = route.path.match(redirectPathRegexp)
|
||||
|
||||
if (match) {
|
||||
const number = parseInt(match[1])
|
||||
if (number === 1) {
|
||||
redirect('/redirect-done')
|
||||
} else {
|
||||
redirect(`/redirect${number - 1}`)
|
||||
}
|
||||
}
|
||||
}
|
3
test/fixtures/spa/nuxt.config.js
vendored
3
test/fixtures/spa/nuxt.config.js
vendored
@ -15,6 +15,9 @@ export default {
|
||||
chunk: '[name].js'
|
||||
}
|
||||
},
|
||||
router: {
|
||||
middleware: 'middleware'
|
||||
},
|
||||
plugins: [
|
||||
'~/plugins/error.js'
|
||||
]
|
||||
|
17
test/fixtures/spa/pages/redirect-done.vue
vendored
Normal file
17
test/fixtures/spa/pages/redirect-done.vue
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div>Redirect Done Page</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
layout: 'default',
|
||||
created() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('redirect-done created')
|
||||
},
|
||||
mounted() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('redirect-done mounted')
|
||||
}
|
||||
}
|
||||
</script>
|
@ -99,6 +99,43 @@ describe('spa', () => {
|
||||
|
||||
const { $data } = window.$nuxt.$route.matched[0].instances.default
|
||||
expect(Object.keys($data).length).toBe(1)
|
||||
consola.log.mockClear()
|
||||
})
|
||||
|
||||
test('/redirect-done (no redirect)', async () => {
|
||||
const { html } = await renderRoute('/redirect-done')
|
||||
expect(html).toContain('<div>Redirect Done Page</div>')
|
||||
expect(consola.log).toHaveBeenCalledWith('redirect-done created')
|
||||
expect(consola.log).toHaveBeenCalledWith('redirect-done mounted')
|
||||
expect(consola.log).toHaveBeenCalledTimes(2)
|
||||
consola.log.mockClear()
|
||||
})
|
||||
|
||||
test('/redirect1 (redirect 1 time)', async () => {
|
||||
const { html } = await renderRoute('/redirect1')
|
||||
expect(html).toContain('<div>Redirect Done Page</div>')
|
||||
expect(consola.log).toHaveBeenCalledWith('redirect-done created')
|
||||
expect(consola.log).toHaveBeenCalledWith('redirect-done mounted')
|
||||
expect(consola.log).toHaveBeenCalledTimes(2)
|
||||
consola.log.mockClear()
|
||||
})
|
||||
|
||||
test('/redirect2 (redirect 2 times)', async () => {
|
||||
const { html } = await renderRoute('/redirect2')
|
||||
expect(html).toContain('<div>Redirect Done Page</div>')
|
||||
expect(consola.log).toHaveBeenCalledWith('redirect-done created')
|
||||
expect(consola.log).toHaveBeenCalledWith('redirect-done mounted')
|
||||
expect(consola.log).toHaveBeenCalledTimes(2)
|
||||
consola.log.mockClear()
|
||||
})
|
||||
|
||||
test('/redirect10 (redirect 10 times)', async () => {
|
||||
const { html } = await renderRoute('/redirect10')
|
||||
expect(html).toContain('<div>Redirect Done Page</div>')
|
||||
expect(consola.log).toHaveBeenCalledWith('redirect-done created')
|
||||
expect(consola.log).toHaveBeenCalledWith('redirect-done mounted')
|
||||
expect(consola.log).toHaveBeenCalledTimes(2)
|
||||
consola.log.mockClear()
|
||||
})
|
||||
|
||||
// Close server and ask nuxt to stop listening to file changes
|
||||
|
Loading…
Reference in New Issue
Block a user