From: Eduardo San Martin Morote Date: Thu, 16 Apr 2020 12:28:24 +0000 (+0200) Subject: refactor(view): replace useView with a prop X-Git-Tag: v4.0.0-alpha.6~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80c827167713e40f86377bc59154fb91b123938a;p=thirdparty%2Fvuejs%2Frouter.git refactor(view): replace useView with a prop Following https://github.com/vuejs/rfcs/pull/153 --- diff --git a/e2e/modal/index.ts b/e2e/modal/index.ts index 278343e4..e874b852 100644 --- a/e2e/modal/index.ts +++ b/e2e/modal/index.ts @@ -1,4 +1,4 @@ -import { createRouter, createWebHistory, useRoute, useView } from '../../src' +import { createRouter, createWebHistory, useRoute } from '../../src' import { RouteComponent, RouteLocationNormalizedLoaded } from '../../src/types' import { createApp, readonly, ref, watchEffect, computed, toRefs } from 'vue' @@ -137,14 +137,13 @@ const app = createApp({ } }) const historyState = computed(() => route.fullPath && window.history.state) - const ViewComponent = useView({ route: routeWithModal, name: 'default' }) - return { route, ViewComponent, historyState, ...toRefs(route) } + return { route, routeWithModal, historyState, ...toRefs(route) } }, template: `
- +
`, }) diff --git a/src/components/View.ts b/src/components/View.ts index 113fb228..5d5237de 100644 --- a/src/components/View.ts +++ b/src/components/View.ts @@ -7,88 +7,14 @@ import { computed, ref, ComponentPublicInstance, - unref, - SetupContext, - toRefs, } from 'vue' -import { VueUseOptions, RouteLocationNormalizedLoaded } from '../types' +import { RouteLocationNormalizedLoaded } from '../types' import { matchedRouteKey, viewDepthKey, routeLocationKey, } from '../utils/injectionSymbols' -interface ViewProps { - route: RouteLocationNormalizedLoaded - name: string -} - -type UseViewOptions = VueUseOptions - -export function useView(options: UseViewOptions) { - const depth: number = inject(viewDepthKey, 0) - provide(viewDepthKey, depth + 1) - - const matchedRoute = computed( - () => - unref(options.route).matched[depth] as - | ViewProps['route']['matched'][any] - | undefined - ) - const ViewComponent = computed( - () => - matchedRoute.value && matchedRoute.value.components[unref(options.name)] - ) - - const propsData = computed(() => { - // propsData only gets called if ViewComponent.value exists and it depends on matchedRoute.value - const { props } = matchedRoute.value! - if (!props) return {} - const route = unref(options.route) - if (props === true) return route.params - - return typeof props === 'object' ? props : props(route) - }) - - provide(matchedRouteKey, matchedRoute) - - const viewRef = ref() - - function onVnodeMounted() { - // if we mount, there is a matched record - matchedRoute.value!.instances[unref(options.name)] = viewRef.value - // TODO: trigger beforeRouteEnter hooks - // TODO: watch name to update the instance record - } - - return (_props: any, { attrs, slots }: SetupContext) => { - // we nee the value at the time we render because when we unmount, we - // navigated to a different location so the value is different - const currentMatched = matchedRoute.value - const name = unref(options.name) - function onVnodeUnmounted() { - if (currentMatched) { - // remove the instance reference to prevent leak - currentMatched.instances[name] = null - } - } - - let Component = ViewComponent.value - const props: Parameters[1] = { - ...(Component && propsData.value), - ...attrs, - onVnodeMounted, - onVnodeUnmounted, - ref: viewRef, - } - - const children = - Component && slots.default && slots.default({ Component, props }) - - return children ? children : Component ? h(Component, props) : null - } -} - export const View = defineComponent({ name: 'RouterView', props: { @@ -96,12 +22,76 @@ export const View = defineComponent({ type: String as PropType, default: 'default', }, + route: Object as PropType, }, - setup(props, context) { - const route = inject(routeLocationKey)! - const renderView = useView({ route, name: toRefs(props).name }) + setup(props, { attrs, slots }) { + const realRoute = inject(routeLocationKey)! + const route = computed(() => props.route || realRoute) + + const depth: number = inject(viewDepthKey, 0) + provide(viewDepthKey, depth + 1) + + const matchedRoute = computed( + () => + route.value.matched[depth] as + | RouteLocationNormalizedLoaded['matched'][any] + | undefined + ) + const ViewComponent = computed( + () => matchedRoute.value && matchedRoute.value.components[props.name] + ) + + const propsData = computed(() => { + // propsData only gets called if ViewComponent.value exists and it depends on matchedRoute.value + const { props } = matchedRoute.value! + if (!props) return {} + if (props === true) return route.value.params + + return typeof props === 'object' ? props : props(route.value) + }) + + provide(matchedRouteKey, matchedRoute) + + const viewRef = ref() + + function onVnodeMounted() { + // if we mount, there is a matched record + matchedRoute.value!.instances[props.name] = viewRef.value + // TODO: trigger beforeRouteEnter hooks + // TODO: watch name to update the instance record + } - return () => renderView(null, context) + return () => { + // we nee the value at the time we render because when we unmount, we + // navigated to a different location so the value is different + const currentMatched = matchedRoute.value + function onVnodeUnmounted() { + if (currentMatched) { + // remove the instance reference to prevent leak + currentMatched.instances[props.name] = null + } + } + + let Component = ViewComponent.value + const componentProps: Parameters[1] = { + ...(Component && propsData.value), + ...attrs, + onVnodeMounted, + onVnodeUnmounted, + ref: viewRef, + } + + const children = + Component && + slots.default && + slots.default({ Component, props: componentProps }) + + return children + ? children + : Component + ? h(Component, componentProps) + : null + } }, }) diff --git a/src/index.ts b/src/index.ts index ba7b0ba5..6849db0a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,7 +36,7 @@ export { export { onBeforeRouteLeave } from './navigationGuards' export { Link, useLink } from './components/Link' -export { View, useView } from './components/View' +export { View } from './components/View' export { createWebHistory, createMemoryHistory, createWebHashHistory }