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