diff --git a/playground/App.vue b/playground/App.vue index 20e7de8bb..1e25a4d86 100644 --- a/playground/App.vue +++ b/playground/App.vue @@ -66,6 +66,9 @@
  • Home
  • +
  • + AppLink Home +
  • /always-redirect
  • @@ -183,15 +186,21 @@ diff --git a/playground/index.html b/playground/index.html index 396abe5d4..824c042ac 100644 --- a/playground/index.html +++ b/playground/index.html @@ -14,6 +14,11 @@ .router-link-exact-active { color: red; } + .router-link { + padding: 2px; + display: block; + border: 1px solid red; + } .long { background-color: lightgray; height: 3000px; diff --git a/src/RouterLink.ts b/src/RouterLink.ts index 0dbef7140..6be888bcd 100644 --- a/src/RouterLink.ts +++ b/src/RouterLink.ts @@ -12,7 +12,12 @@ import { getCurrentInstance, watchEffect, } from 'vue' -import { RouteLocationRaw, VueUseOptions, RouteLocation } from './types' +import { + RouteLocationRaw, + VueUseOptions, + RouteLocation, + RouteLocationNormalized, +} from './types' import { isSameRouteLocationParams, isSameRouteRecord } from './location' import { routerKey, routeLocationKey } from './injectionSymbols' import { RouteRecord } from './matcher/types' @@ -58,6 +63,12 @@ export interface RouterLinkProps extends RouterLinkOptions { | 'false' } +export interface UseLinkDevtoolsContext { + route: RouteLocationNormalized & { href: string } + isActive: boolean + isExactActive: boolean +} + export type UseLinkOptions = VueUseOptions // TODO: we could allow currentRoute as a prop to expose `isActive` and @@ -122,6 +133,30 @@ export function useLink(props: UseLinkOptions) { return Promise.resolve() } + // devtools only + if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && isBrowser) { + const instance = getCurrentInstance() + if (!instance) return + const linkContextDevtools: UseLinkDevtoolsContext = { + route: route.value, + isActive: isActive.value, + isExactActive: isExactActive.value, + } + + // @ts-expect-error: this is internal + instance.__vrl_devtools = instance.__vrl_devtools || [] + // @ts-expect-error: this is internal + instance.__vrl_devtools.push(linkContextDevtools) + watchEffect( + () => { + linkContextDevtools.route = route.value + linkContextDevtools.isActive = isActive.value + linkContextDevtools.isExactActive = isExactActive.value + }, + { flush: 'post' } + ) + } + return { route, href: computed(() => route.value.href), @@ -173,26 +208,6 @@ export const RouterLinkImpl = /*#__PURE__*/ defineComponent({ )]: link.isExactActive, })) - // devtools only - if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && isBrowser) { - const instance = getCurrentInstance() - watchEffect( - () => { - if (!instance) return - ;(instance as any).__vrl_route = link.route - }, - { flush: 'post' } - ) - watchEffect( - () => { - if (!instance) return - ;(instance as any).__vrl_active = link.isActive - ;(instance as any).__vrl_exactActive = link.isExactActive - }, - { flush: 'post' } - ) - } - return () => { const children = slots.default && slots.default(link) return props.custom diff --git a/src/devtools.ts b/src/devtools.ts index c54b5e102..31b63d7b1 100644 --- a/src/devtools.ts +++ b/src/devtools.ts @@ -14,6 +14,7 @@ import { RouterMatcher } from './matcher' import { RouteRecordMatcher } from './matcher/pathMatcher' import { PathParser } from './matcher/pathParserRanker' import { Router } from './router' +import { UseLinkDevtoolsContext } from './RouterLink' import { RouteLocation, RouteLocationNormalized } from './types' import { assign } from './utils' @@ -87,30 +88,30 @@ export function addDevtools(app: App, router: Router, matcher: RouterMatcher) { // mark router-link as active api.on.visitComponentTree(({ treeNode: node, componentInstance }) => { - if (node.name === 'RouterLink') { - if (componentInstance.__vrl_route) { - node.tags.push({ - label: (componentInstance.__vrl_route as RouteLocation).path, - textColor: 0, - backgroundColor: ORANGE_400, - }) - } - - if (componentInstance.__vrl_exactActive) { - node.tags.push({ - label: 'exact', - textColor: 0, - backgroundColor: LIME_500, - }) - } + // if multiple useLink are used + if (Array.isArray(componentInstance.__vrl_devtools)) { + componentInstance.__devtoolsApi = api + ;( + componentInstance.__vrl_devtools as UseLinkDevtoolsContext[] + ).forEach(devtoolsData => { + let backgroundColor = ORANGE_400 + let tooltip: string = '' + + if (devtoolsData.isExactActive) { + backgroundColor = LIME_500 + tooltip = 'This is exactly active' + } else if (devtoolsData.isActive) { + backgroundColor = BLUE_600 + tooltip = 'This link is active' + } - if (componentInstance.__vrl_active) { node.tags.push({ - label: 'active', + label: devtoolsData.route.path, textColor: 0, - backgroundColor: BLUE_600, + tooltip, + backgroundColor, }) - } + }) } }) @@ -119,6 +120,7 @@ export function addDevtools(app: App, router: Router, matcher: RouterMatcher) { refreshRoutesView() api.notifyComponentUpdate() api.sendInspectorTree(routerInspectorId) + api.sendInspectorState(routerInspectorId) }) const navigationsLayerId = 'router:navigations:' + id