From: Eduardo San Martin Morote Date: Tue, 23 Jun 2020 15:07:58 +0000 (+0200) Subject: refactor: move install code to router.ts X-Git-Tag: v4.0.0-alpha.14~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=edd9c06e7e0026485713e6505ab4560f03c2cf9c;p=thirdparty%2Fvuejs%2Frouter.git refactor: move install code to router.ts --- diff --git a/src/index.ts b/src/index.ts index 9c452e3d..2941e54a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,10 @@ +import { + NavigationGuard, + RouteLocationNormalizedLoaded, + NavigationGuardWithThis, +} from './types' +import { Router } from './router' + export { createWebHistory } from './history/html5' export { createMemoryHistory } from './history/memory' export { createWebHashHistory } from './history/hash' @@ -49,3 +56,55 @@ export { RouterLink, useLink, RouterLinkProps } from './RouterLink' export { RouterView, RouterViewProps } from './RouterView' export * from './useApi' + +declare module '@vue/runtime-core' { + interface ComponentCustomOptions { + /** + * Guard called when the router is navigating to the route that is rendering + * this component from a different route. Differently from `beforeRouteUpdate` + * and `beforeRouteLeave`, `beforeRouteEnter` does not have access to the + * component instance through `this` because it triggers before the component + * is even mounted. + * + * @param to - RouteLocationRaw we are navigating to + * @param from - RouteLocationRaw we are navigating from + * @param next - function to validate, cancel or modify (by redirecting) the + * navigation + */ + beforeRouteEnter?: NavigationGuardWithThis + + /** + * Guard called whenever the route that renders this component has changed but + * it is reused for the new route. This allows you to guard for changes in + * params, the query or the hash. + * + * @param to - RouteLocationRaw we are navigating to + * @param from - RouteLocationRaw we are navigating from + * @param next - function to validate, cancel or modify (by redirecting) the + * navigation + */ + beforeRouteUpdate?: NavigationGuard + + /** + * Guard called when the router is navigating away from the current route that + * is rendering this component. + * + * @param to - RouteLocationRaw we are navigating to + * @param from - RouteLocationRaw we are navigating from + * @param next - function to validate, cancel or modify (by redirecting) the + * navigation + */ + beforeRouteLeave?: NavigationGuard + } + + interface ComponentCustomProperties { + /** + * Normalized current location. See {@link RouteLocationNormalizedLoaded}. + */ + $route: RouteLocationNormalizedLoaded + /** + * {@link Router} instance used by the application. + */ + $router: Router + } +} diff --git a/src/install.ts b/src/install.ts deleted file mode 100644 index 61f156e1..00000000 --- a/src/install.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { App, ComputedRef, reactive, computed } from 'vue' -import { Router } from './router' -import { RouterLink } from './RouterLink' -import { RouterView } from './RouterView' -import { isBrowser } from './utils' -import { - START_LOCATION_NORMALIZED, - RouteLocationNormalizedLoaded, - NavigationGuardWithThis, - NavigationGuard, -} from './types' -import { routerKey, routeLocationKey } from './injectionSymbols' -import { warn } from './warning' - -declare module '@vue/runtime-core' { - interface ComponentCustomOptions { - /** - * Guard called when the router is navigating to the route that is rendering - * this component from a different route. Differently from `beforeRouteUpdate` - * and `beforeRouteLeave`, `beforeRouteEnter` does not have access to the - * component instance through `this` because it triggers before the component - * is even mounted. - * - * @param to - RouteLocationRaw we are navigating to - * @param from - RouteLocationRaw we are navigating from - * @param next - function to validate, cancel or modify (by redirecting) the - * navigation - */ - beforeRouteEnter?: NavigationGuardWithThis - - /** - * Guard called whenever the route that renders this component has changed but - * it is reused for the new route. This allows you to guard for changes in - * params, the query or the hash. - * - * @param to - RouteLocationRaw we are navigating to - * @param from - RouteLocationRaw we are navigating from - * @param next - function to validate, cancel or modify (by redirecting) the - * navigation - */ - beforeRouteUpdate?: NavigationGuard - - /** - * Guard called when the router is navigating away from the current route that - * is rendering this component. - * - * @param to - RouteLocationRaw we are navigating to - * @param from - RouteLocationRaw we are navigating from - * @param next - function to validate, cancel or modify (by redirecting) the - * navigation - */ - beforeRouteLeave?: NavigationGuard - } - - interface ComponentCustomProperties { - /** - * Normalized current location. See {@link RouteLocationNormalizedLoaded}. - */ - $route: RouteLocationNormalizedLoaded - /** - * {@link Router} instance used by the application. - */ - $router: Router - } -} - -export function applyRouterPlugin(app: App, router: Router) { - app.component('RouterLink', RouterLink) - app.component('RouterView', RouterView) - - // TODO: add tests - app.config.globalProperties.$router = router - Object.defineProperty(app.config.globalProperties, '$route', { - get: () => router.currentRoute.value, - }) - - // this initial navigation is only necessary on client, on server it doesn't - // make sense because it will create an extra unnecessary navigation and could - // lead to problems - if ( - isBrowser && - // @ts-ignore: used for the initial navigation client side to avoid pushing - // multiple times when the router is used in multiple apps - !router._started && - router.currentRoute.value === START_LOCATION_NORMALIZED - ) { - // @ts-ignore: see above - router._started = true - router.push(router.history.location.fullPath).catch(err => { - if (__DEV__) warn('Unexpected error when starting the router:', err) - }) - } - - const reactiveRoute = {} as { - [k in keyof RouteLocationNormalizedLoaded]: ComputedRef< - RouteLocationNormalizedLoaded[k] - > - } - for (let key in START_LOCATION_NORMALIZED) { - // @ts-ignore: the key matches - reactiveRoute[key] = computed(() => router.currentRoute.value[key]) - } - - app.provide(routerKey, router) - app.provide(routeLocationKey, reactive(reactiveRoute)) -} diff --git a/src/router.ts b/src/router.ts index 439dd40d..7f41d616 100644 --- a/src/router.ts +++ b/src/router.ts @@ -38,12 +38,22 @@ import { parseQuery as originalParseQuery, stringifyQuery as originalStringifyQuery, } from './query' -import { shallowRef, Ref, nextTick, App } from 'vue' +import { + shallowRef, + Ref, + nextTick, + App, + ComputedRef, + reactive, + unref, +} from 'vue' import { RouteRecord, RouteRecordNormalized } from './matcher/types' import { parseURL, stringifyURL, isSameRouteLocation } from './location' import { extractComponentsGuards, guardToPromiseFn } from './navigationGuards' -import { applyRouterPlugin } from './install' import { warn } from './warning' +import { RouterLink } from './RouterLink' +import { RouterView } from './RouterView' +import { routerKey, routeLocationKey } from './injectionSymbols' /** * Internal type to define an ErrorHandler @@ -817,6 +827,8 @@ export function createRouter(options: RouterOptions): Router { ) } + let started: boolean | undefined + const router: Router = { currentRoute, @@ -842,7 +854,45 @@ export function createRouter(options: RouterOptions): Router { history: routerHistory, install(app: App) { - applyRouterPlugin(app, this) + const router = this + app.component('RouterLink', RouterLink) + app.component('RouterView', RouterView) + + // TODO: add tests + app.config.globalProperties.$router = router + Object.defineProperty(app.config.globalProperties, '$route', { + get: () => unref(currentRoute), + }) + + // this initial navigation is only necessary on client, on server it doesn't + // make sense because it will create an extra unnecessary navigation and could + // lead to problems + if ( + isBrowser && + // used for the initial navigation client side to avoid pushing + // multiple times when the router is used in multiple apps + !started && + currentRoute.value === START_LOCATION_NORMALIZED + ) { + // see above + started = true + push(routerHistory.location.fullPath).catch(err => { + if (__DEV__) warn('Unexpected error when starting the router:', err) + }) + } + + const reactiveRoute = {} as { + [k in keyof RouteLocationNormalizedLoaded]: ComputedRef< + RouteLocationNormalizedLoaded[k] + > + } + for (let key in START_LOCATION_NORMALIZED) { + // @ts-ignore: the key matches + reactiveRoute[key] = computed(() => currentRoute.value[key]) + } + + app.provide(routerKey, router) + app.provide(routeLocationKey, reactive(reactiveRoute)) }, }