]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat: wip suspense
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 25 Jan 2021 09:50:23 +0000 (10:50 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 28 Jun 2021 15:10:17 +0000 (17:10 +0200)
e2e/suspended-router-view/index.ts
src/RouterViewSuspended.ts
src/index.ts
src/router.ts

index 24c8007e3d2a20a29bf8c52a7b0dcb3bc2ba8cba..1a9e8ea07478a6f611a9084522276db8f3da4bde 100644 (file)
@@ -1,4 +1,4 @@
-import { createRouter, createWebHistory } from '../../src'
+import { createRouter, createWebHistory, RouterViewSuspended } from '../../src'
 import { createApp, defineComponent, onErrorCaptured } from 'vue'
 
 const delay = (t: number) => new Promise(r => setTimeout(r, t))
@@ -18,6 +18,7 @@ const ViewData = defineComponent({
   template: `
   <div>
     <h1>With Data</h1>
+    <p>{{ $route.path }}</p>
 
     <router-view/>
 
@@ -27,7 +28,7 @@ const ViewData = defineComponent({
   async setup() {
     await delay(300)
 
-    throw new Error('oops')
+    // throw new Error('oops')
 
     return {}
   },
@@ -85,12 +86,13 @@ const app = createApp({
         <li><router-link to="/data-2/data">Suspended nested (2)</router-link></li>
       </ul>
 
-      <router-view-suspended />
+      <router-view  />
 
     </div>
   `,
 })
 app.use(router)
+app.component('RouterView', RouterViewSuspended)
 
 window.vm = app.mount('#app')
 window.r = router
index 0d91b9fcff6a73a1633c57c337ba9fcf48d46264..8526d7126ed8aab22ce0b95f9dda06e6027a3f38 100644 (file)
@@ -11,6 +11,7 @@ import {
   AllowedComponentProps,
   ComponentCustomProps,
   watch,
+  Suspense,
 } from 'vue'
 import {
   RouteLocationNormalized,
@@ -26,14 +27,14 @@ import {
 import { assign } from './utils'
 import { isSameRouteRecord } from './location'
 
-export interface RouterViewProps {
+export interface RouterViewSuspendedProps {
   name?: string
   // allow looser type for user facing api
   route?: RouteLocationNormalized
 }
 
 export const RouterViewSuspendedImpl = /*#__PURE__*/ defineComponent({
-  name: 'RouterView',
+  name: 'RouterViewSuspended',
   // #674 we manually inherit them
   inheritAttrs: false,
   props: {
@@ -46,16 +47,22 @@ export const RouterViewSuspendedImpl = /*#__PURE__*/ defineComponent({
 
   setup(props, { attrs }) {
     const injectedRoute = inject(routerViewLocationKey)!
+    const isSuspended = inject('isSuspended', false as boolean)
+    // TODO: should be pending route -> after leave, update and global navigation guards
     const suspendedRoute = inject(suspendedRouteKey)!
     const routeToDisplay = computed(() => props.route || injectedRoute.value)
     const depth = inject(viewDepthKey, 0)
     const matchedRouteRef = computed<RouteLocationMatched | undefined>(
       () => routeToDisplay.value.matched[depth]
     )
+    const suspendedMatchedRouteRef = computed<
+      RouteLocationMatched | undefined | null
+    >(() => suspendedRoute.value && suspendedRoute.value.matched[depth])
 
     provide(viewDepthKey, depth + 1)
     provide(matchedRouteKey, matchedRouteRef)
     provide(routerViewLocationKey, routeToDisplay)
+    provide('isSuspended', true)
 
     const viewRef = ref<ComponentPublicInstance>()
 
@@ -96,11 +103,17 @@ export const RouterViewSuspendedImpl = /*#__PURE__*/ defineComponent({
     return () => {
       const route = routeToDisplay.value
       const matchedRoute = matchedRouteRef.value
+      const suspendedMatchedRoute = suspendedMatchedRouteRef.value
       const ViewComponent = matchedRoute && matchedRoute.components[props.name]
+      const SuspendedViewComponent =
+        suspendedMatchedRoute && suspendedMatchedRoute.components[props.name]
       // we need the value at the time we render because when we unmount, we
       // navigated to a different location so the value is different
       const currentName = props.name
 
+      console.log('suspended', suspendedMatchedRoute)
+
+      // TODO: should be smarter to still display a suspended component
       if (!ViewComponent) {
         return null
       }
@@ -122,6 +135,18 @@ export const RouterViewSuspendedImpl = /*#__PURE__*/ defineComponent({
         }
       }
 
+      function onPending(...args: any[]) {
+        console.log('pending', ...args)
+      }
+
+      function onResolve(...args: any[]) {
+        console.log('resolve', ...args)
+      }
+
+      function onFallback(...args: any[]) {
+        console.log('fallback', ...args)
+      }
+
       const component = h(
         ViewComponent,
         assign({}, routeProps, attrs, {
@@ -130,7 +155,18 @@ export const RouterViewSuspendedImpl = /*#__PURE__*/ defineComponent({
         })
       )
 
-      return component
+      return isSuspended
+        ? component
+        : h(
+            Suspense,
+            {
+              timeout: 0,
+              onPending,
+              onResolve,
+              onFallback,
+            },
+            component
+          )
     }
   },
 })
@@ -145,6 +181,6 @@ export const RouterViewSuspended = (RouterViewSuspendedImpl as any) as {
     $props: AllowedComponentProps &
       ComponentCustomProps &
       VNodeProps &
-      RouterViewProps
+      RouterViewSuspendedProps
   }
 }
index d2d2497f0984daa17ba0079a161742522e32b852..301d0b55ca29eb08a6af5f576b2dd91d65e2b014 100644 (file)
@@ -81,6 +81,10 @@ export {
   UseLinkOptions,
 } from './RouterLink'
 export { RouterView, RouterViewProps } from './RouterView'
+export {
+  RouterViewSuspended,
+  RouterViewSuspendedProps,
+} from './RouterViewSuspended'
 
 export * from './useApi'
 
index 3010ba3a35621f3ebe23ba433f7324d49ee8944b..5107e192778f33bd3ba857952b5ea2458d77cc50 100644 (file)
@@ -61,7 +61,6 @@ import { extractComponentsGuards, guardToPromiseFn } from './navigationGuards'
 import { warn } from './warning'
 import { RouterLink } from './RouterLink'
 import { RouterView } from './RouterView'
-import { RouterViewSuspended } from './RouterViewSuspended'
 import {
   routeLocationKey,
   routerKey,
@@ -1156,7 +1155,6 @@ export function createRouter(options: RouterOptions): Router {
       const router = this
       app.component('RouterLink', RouterLink)
       app.component('RouterView', RouterView)
-      app.component('RouterViewSuspended', RouterViewSuspended)
 
       app.config.globalProperties.$router = router
       Object.defineProperty(app.config.globalProperties, '$route', {