From: Eduardo San Martin Morote Date: Thu, 3 Dec 2020 09:49:41 +0000 (+0100) Subject: fix(router-view): properly use route prop when nested X-Git-Tag: v4.0.0~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b74051a6bde7524d1a7cc6cc1daacb213987faa0;p=thirdparty%2Fvuejs%2Frouter.git fix(router-view): properly use route prop when nested --- diff --git a/__tests__/mount.ts b/__tests__/mount.ts index c83567c8..41976e43 100644 --- a/__tests__/mount.ts +++ b/__tests__/mount.ts @@ -16,7 +16,10 @@ import { import { compile } from '@vue/compiler-dom' import * as runtimeDom from '@vue/runtime-dom' import { RouteLocationNormalizedLoose } from './utils' -import { routeLocationKey } from '../src/injectionSymbols' +import { + routeLocationKey, + routerViewLocationKey, +} from '../src/injectionSymbols' import { Router } from '../src' export interface MountOptions { @@ -183,6 +186,7 @@ export function createMockedRoute(initialValue: RouteLocationNormalizedLoose) { set, provides: { [routeLocationKey as symbol]: value, + [routerViewLocationKey as symbol]: routeRef, }, } } diff --git a/e2e/modal/index.ts b/e2e/modal/index.ts index 2987cc66..1e35e352 100644 --- a/e2e/modal/index.ts +++ b/e2e/modal/index.ts @@ -47,6 +47,8 @@ const Home = defineComponent({ + +
@@ -110,6 +112,10 @@ const About = defineComponent({ }, }) +const Child = defineComponent({ + template: `
child
`, +}) + const UserDetails = defineComponent({ template: `

User #{{ id }}

@@ -121,8 +127,7 @@ const UserDetails = defineComponent({ props: { id: { type: String, - // FIXME: setting this to true fails with props: true, as if it didn't fit the definition of RouteComponent - required: false, + required: true, }, }, data: () => ({ users }), @@ -132,7 +137,14 @@ const webHistory = createWebHistory('/' + __dirname) const router = createRouter({ history: webHistory, routes: [ - { path: '/', component: Home }, + { + path: '/', + component: Home, + children: [ + // to check that displaying the modal doesn't change this + { path: '', component: Child }, + ], + }, { path: '/about', component: About }, { path: '/users/:id', props: true, name: 'user', component: UserDetails }, ], diff --git a/e2e/specs/modal.js b/e2e/specs/modal.js index 236ac67e..f47e3686 100644 --- a/e2e/specs/modal.js +++ b/e2e/specs/modal.js @@ -14,11 +14,13 @@ module.exports = { .waitForElementPresent('#app > *', 1000) .assert.containsText('h1', 'Home') .assert.not.visible('dialog') + .assert.containsText('.child', 'child') .click('li:nth-child(2) button') .assert.urlEquals(baseURL + '/users/1') .assert.visible('dialog') .assert.containsText('dialog', 'User #1') + .assert.containsText('.child', 'child') .end() }, diff --git a/src/RouterView.ts b/src/RouterView.ts index 323b2d14..f491d4f1 100644 --- a/src/RouterView.ts +++ b/src/RouterView.ts @@ -22,7 +22,7 @@ import { import { matchedRouteKey, viewDepthKey, - routeLocationKey, + routerViewLocationKey, } from './injectionSymbols' import { assign } from './utils' import { warn } from './warning' @@ -47,14 +47,16 @@ export const RouterViewImpl = /*#__PURE__*/ defineComponent({ setup(props, { attrs, slots }) { __DEV__ && warnDeprecatedUsage() - const injectedRoute = inject(routeLocationKey)! + const injectedRoute = inject(routerViewLocationKey)! + const routeToDisplay = computed(() => props.route || injectedRoute.value) const depth = inject(viewDepthKey, 0) const matchedRouteRef = computed( - () => (props.route || injectedRoute).matched[depth] + () => routeToDisplay.value.matched[depth] ) provide(viewDepthKey, depth + 1) provide(matchedRouteKey, matchedRouteRef) + provide(routerViewLocationKey, routeToDisplay) const viewRef = ref() @@ -93,7 +95,7 @@ export const RouterViewImpl = /*#__PURE__*/ defineComponent({ ) return () => { - const route = props.route || injectedRoute + const route = routeToDisplay.value const matchedRoute = matchedRouteRef.value const ViewComponent = matchedRoute && matchedRoute.components[props.name] // we need the value at the time we render because when we unmount, we diff --git a/src/injectionSymbols.ts b/src/injectionSymbols.ts index b23ea5e3..0d345ea1 100644 --- a/src/injectionSymbols.ts +++ b/src/injectionSymbols.ts @@ -1,4 +1,4 @@ -import { InjectionKey, ComputedRef } from 'vue' +import { InjectionKey, ComputedRef, Ref } from 'vue' import { RouteLocationNormalizedLoaded } from './types' import { Router } from './router' import { RouteRecordNormalized } from './matcher/types' @@ -35,7 +35,8 @@ export const viewDepthKey = /*#__PURE__*/ PolySymbol( ) as InjectionKey /** - * Allows overriding the router instance returned by `useRouter` in tests. r stands for router + * Allows overriding the router instance returned by `useRouter` in tests. r + * stands for router * * @internal */ @@ -44,10 +45,21 @@ export const routerKey = /*#__PURE__*/ PolySymbol( ) as InjectionKey /** - * Allows overriding the current route returned by `useRoute` in tests. rl stands for route location + * Allows overriding the current route returned by `useRoute` in tests. rl + * stands for route location * * @internal */ export const routeLocationKey = /*#__PURE__*/ PolySymbol( __DEV__ ? 'route location' : 'rl' ) as InjectionKey + +/** + * Allows overriding the current route used by router-view. Internally this is + * used when the `route` prop is passed. + * + * @internal + */ +export const routerViewLocationKey = /*#__PURE__*/ PolySymbol( + __DEV__ ? 'router view location' : 'rvl' +) as InjectionKey> diff --git a/src/router.ts b/src/router.ts index 7aa5490f..15aa5748 100644 --- a/src/router.ts +++ b/src/router.ts @@ -56,7 +56,11 @@ import { extractComponentsGuards, guardToPromiseFn } from './navigationGuards' import { warn } from './warning' import { RouterLink } from './RouterLink' import { RouterView } from './RouterView' -import { routerKey, routeLocationKey } from './injectionSymbols' +import { + routeLocationKey, + routerKey, + routerViewLocationKey, +} from './injectionSymbols' import { addDevtools } from './devtools' /** @@ -1098,6 +1102,7 @@ export function createRouter(options: RouterOptions): Router { app.provide(routerKey, router) app.provide(routeLocationKey, reactive(reactiveRoute)) + app.provide(routerViewLocationKey, currentRoute) let unmountApp = app.unmount installedApps.add(app)