]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
refactor(view): replace useView with a prop
authorEduardo San Martin Morote <posva13@gmail.com>
Thu, 16 Apr 2020 12:28:24 +0000 (14:28 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Thu, 16 Apr 2020 12:28:27 +0000 (14:28 +0200)
Following https://github.com/vuejs/rfcs/pull/153

e2e/modal/index.ts
src/components/View.ts
src/index.ts

index 278343e4cb682e624ca1a67857b0c1ccfead5d4a..e874b852d8fd00da6d10f00e8d47ffd2eb5fdab2 100644 (file)
@@ -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: `
     <div id="app">
-      <component :is="ViewComponent"></component>
+      <router-view :route="routeWithModal"></router-view>
     </div>
   `,
 })
index 113fb2288ce308a7b8cabfcdc351c429792bb691..5d5237dec9b58b9cda80cd371e4bbb18f535e001 100644 (file)
@@ -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<ViewProps>
-
-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<ComponentPublicInstance>()
-
-  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<typeof h>[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<string>,
       default: 'default',
     },
+    route: Object as PropType<RouteLocationNormalizedLoaded>,
   },
 
-  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<ComponentPublicInstance>()
+
+    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<typeof h>[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
+    }
   },
 })
index ba7b0ba5cf538315924402c84f0242ddb1969d4b..6849db0a06d86c96750773ac72f2d2d80e117672 100644 (file)
@@ -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 }