From: Eduardo San Martin Morote Date: Mon, 25 Jan 2021 09:50:23 +0000 (+0100) Subject: feat: wip suspense X-Git-Tag: v4.0.11~37 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e048e0f197a8a10507f4f17e3c855961ff711c0;p=thirdparty%2Fvuejs%2Frouter.git feat: wip suspense --- diff --git a/e2e/suspended-router-view/index.ts b/e2e/suspended-router-view/index.ts index 24c8007e..1a9e8ea0 100644 --- a/e2e/suspended-router-view/index.ts +++ b/e2e/suspended-router-view/index.ts @@ -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: `

With Data

+

{{ $route.path }}

@@ -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({
  • Suspended nested (2)
  • - +
    `, }) app.use(router) +app.component('RouterView', RouterViewSuspended) window.vm = app.mount('#app') window.r = router diff --git a/src/RouterViewSuspended.ts b/src/RouterViewSuspended.ts index 0d91b9fc..8526d712 100644 --- a/src/RouterViewSuspended.ts +++ b/src/RouterViewSuspended.ts @@ -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( () => 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() @@ -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 } } diff --git a/src/index.ts b/src/index.ts index d2d2497f..301d0b55 100644 --- a/src/index.ts +++ b/src/index.ts @@ -81,6 +81,10 @@ export { UseLinkOptions, } from './RouterLink' export { RouterView, RouterViewProps } from './RouterView' +export { + RouterViewSuspended, + RouterViewSuspendedProps, +} from './RouterViewSuspended' export * from './useApi' diff --git a/src/router.ts b/src/router.ts index 3010ba3a..5107e192 100644 --- a/src/router.ts +++ b/src/router.ts @@ -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', {