RouterLink
Navigation component that triggers route navigation on click. On H5 it renders a native <a> element (with href), restoring native link capabilities like semantics, right-click open in new tab, and accessibility recognition; on other platforms it renders a <navigator> with hover-class providing pressed-state feedback.
Import
import RouterLink from '@meng-xi/uni-router/components/router-link/router-link.vue'Direct .vue file import
RouterLink is a standalone Vue component file. You need to import the .vue file path directly, not from the package entry. It's recommended to configure auto-import in pages.json's easycom, or register it globally in main.ts.
Global Registration (Recommended)
// src/main.ts
import { createSSRApp } from 'vue'
import App from './App.vue'
import router from './router'
import RouterLink from '@meng-xi/uni-router/components/router-link/router-link.vue'
export function createApp() {
const app = createSSRApp(App)
app.use(router)
app.component('RouterLink', RouterLink) // Global registration
return { app }
}After registration, you can use <RouterLink> directly in any component without importing each time.
Props
to
- Type:
RouteLocationRaw - Required: Yes
- Description: Target route location, supports the following forms:
- Path string:
'pages/about/about' - Path object:
{ path: 'pages/about/about', query: { id: '1' } } - Named object:
{ name: 'about', query: { id: '1' } }
- Path string:
<!-- Path string -->
<RouterLink to="pages/about/about">About</RouterLink>
<!-- Path object (requires :to binding) -->
<RouterLink :to="{ path: 'pages/about/about', query: { id: '1' } }">Details</RouterLink>
<!-- Named route (recommended) -->
<RouterLink :to="{ name: 'about', query: { id: '1' } }">Details</RouterLink>Object form requires :to binding
When passing an object to the to prop, use :to binding (v-bind:to), not the string attribute to. The string form to="pages/about/about" can be used directly.
Plugin-dependent fields
Plugin-dependent fields such as params, animation, and events are passed through the to object, not as standalone Props. Register the corresponding plugin before using them:
<!-- Pass params (requires ParamsPlugin) -->
<RouterLink :to="{ path: 'pages/detail/detail', params: { id: 123 } }">
<text>View Details</text>
</RouterLink>
<!-- Pass animation (requires AnimationPlugin) -->
<RouterLink :to="{ path: 'pages/about/about', animation: { type: 'slide-in-bottom' } }">
<text>Slide In Bottom</text>
</RouterLink>See Plugin System for details.
replace
- Type:
boolean - Default:
false - Description: Whether to use replace mode for navigation
false→ callsrouter.push(to)true→ callsrouter.replace(to)
<!-- Navigate from login page, avoid leaving login page in stack -->
<RouterLink to="pages/home/home" replace>
<text>Login</text>
</RouterLink>relaunch
- Type:
boolean - Default:
false - Description: Whether to use relaunch mode for navigation (close all pages and open target page)
true→ callsrouter.relaunch(to)- Takes priority over
replace; when bothrelaunchandreplaceare set,relaunchis used
<!-- Logout, clear stack -->
<RouterLink to="pages/login/login" relaunch>
<text>Logout</text>
</RouterLink>
<!-- Return to home from a deep page -->
<RouterLink to="pages/index/index" relaunch>
<text>Back to Home</text>
</RouterLink>hoverClass
- Type:
string - Default:
'navigator-hover' - Description: Style class applied when pressed (non-H5 only), corresponds to
<navigator>'shover-classattribute. On H5 the component renders an<a>and uses native CSS:hoverfor feedback. Set to'none'to disable hover effect
hoverStopPropagation
- Type:
boolean - Default:
false - Description: Whether to prevent ancestor nodes from showing hover effect
hoverStartTime
- Type:
number - Default:
50 - Description: Duration after press before hover effect appears, in ms
hoverStayTime
- Type:
number - Default:
600 - Description: Duration hover effect remains after release, in ms
Events
error
- Parameter:
(error: NavigationFailure) - Description: Emitted when navigation fails, e.g., guard abort, duplicate navigation, etc. When not listened to, errors are silently handled without causing Unhandled Promise Rejection.
<RouterLink to="pages/about/about" @error="onNavError">
<text>About Us</text>
</RouterLink>import { NavigationFailure, RouterErrorCode } from '@meng-xi/uni-router'
function onNavError(error: NavigationFailure) {
switch (error.code) {
case RouterErrorCode.NAVIGATION_ABORTED:
console.log('Navigation aborted by guard')
break
case RouterErrorCode.NAVIGATION_DUPLICATED:
console.log('Already on this page')
break
case RouterErrorCode.NAVIGATION_API_ERROR:
uni.showToast({ title: 'Navigation failed', icon: 'none' })
console.error('Original error:', error.cause)
break
}
}Recommend listening to the error event
When the error event is not listened to, navigation failures are silently handled (no unhandled Promise rejection). However, it's recommended to listen and handle errors in production to improve user experience.
navigated
- Parameter:
(eventChannel: EventChannel | undefined) - Description: Emitted after a successful navigation, returns
eventChannelfor page communication.eventChannelis only available inpushmode by default; withuseUniEventChannelenabled,replace/relaunchalso returneventChannel.
<RouterLink
:to="{ path: 'pages/detail/detail', query: { id: '1' } }"
@navigated="onNavigated"
>
<text>View Details</text>
</RouterLink>function onNavigated(eventChannel) {
// Send event to the target page
eventChannel?.emit('init', { message: 'Data from the opener page' })
}Slots
default
Default slot for the navigation link content:
<RouterLink to="pages/about/about">
<text>Go to About</text>
</RouterLink>
<!-- Complex content -->
<RouterLink :to="{ name: 'detail', query: { id: item.id } }">
<view class="card">
<image :src="item.cover" />
<text>{{ item.title }}</text>
<text>{{ item.desc }}</text>
</view>
</RouterLink>Examples
Basic Usage
<template>
<RouterLink to="pages/about/about">
<text>About Us</text>
</RouterLink>
</template>
<script setup lang="ts">
import RouterLink from '@meng-xi/uni-router/components/router-link/router-link.vue'
</script>Replace Mode
<!-- After successful login, navigate to home, avoid leaving login page in stack -->
<RouterLink to="pages/home/home" replace>
<text>Login</text>
</RouterLink>Relaunch Mode
<!-- Logout, clear all pages -->
<RouterLink to="pages/login/login" relaunch>
<text>Logout</text>
</RouterLink>With Query Parameters
<!-- String form -->
<RouterLink to="pages/about/about?id=1&tab=info">
<text>Article Detail</text>
</RouterLink>
<!-- Object form (recommended) -->
<RouterLink :to="{ name: 'about', query: { id: '1', tab: 'info' } }">
<text>Article Detail</text>
</RouterLink>Handling Navigation Errors
<RouterLink :to="{ name: 'admin' }" @error="onNavError">
<text>Admin Panel</text>
</RouterLink>List Scenario
<template>
<view class="list">
<RouterLink
v-for="item in list"
:key="item.id"
:to="{ name: 'detail', query: { id: item.id } }"
>
<view class="card">
<text>{{ item.title }}</text>
</view>
</RouterLink>
</view>
</template>H5 Native Link Capabilities
On H5, RouterLink renders a native <a> element (with a real href) via #ifdef H5 conditional compilation, restoring the browser's native link capabilities:
| Capability | Description |
|---|---|
| Link semantics | A real <a> element exists in the page, preserving semantic structure |
| Right-click open in new tab | The context menu works normally; "Open link in new tab" opens the target route |
| Browser address recognition | The status bar shows the target address on hover; recognized as a hyperlink |
| Accessibility support | Screen readers and other assistive tools correctly identify the link |
| Native href behavior | Modified clicks (Ctrl/Cmd/Shift/Alt) or middle clicks keep browser default behavior |
A normal left click still prevents the default jump and delegates to the router, so the guard chain (beforeEach, etc.) still runs:
// Component internals (H5 branch)
async function handleClick(event: unknown) {
// #ifdef H5
const e = event as MouseEvent
// Modified or middle click → keep native browser behavior (open in new tab, etc.)
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || e.button !== 0) {
return
}
e.preventDefault()
// #endif
// Router navigation (guard chain runs)
await navigate()
}Platform differences (conditional compilation)
- H5: renders
<a>(withhref); the href automatically adapts to hash routing (#prefix), so right-click "open in new tab" routes correctly - App / Mini-program: renders
<navigator>(uni-app native navigation component)
Differences from vue-router RouterLink
| Feature | vue-router | Uni Router |
|---|---|---|
| Host element | <a> | H5: <a>; other platforms: <navigator> |
to type | string | object | string | object |
replace | ✅ | ✅ |
relaunch | ❌ | ✅ |
custom | ✅ | ❌ |
active-class | ✅ | ❌ |
exact-active-class | ✅ | ❌ |
v-slot scoped slot | ✅ | ❌ |
hover-class | ❌ | ✅ |
error event | ❌ | ✅ |
navigated event | ❌ | ✅ |
Why active-class is not supported
vue-router's active-class relies on real-time browser URL matching, while uni-app's navigation is managed by the native page stack, and components cannot perceive the current page state. To highlight the link corresponding to the current page, manually check via useRoute():
<script setup lang="ts">
import { useRoute } from '@meng-xi/uni-router'
const route = useRoute()
const isActive = (name: string) => route.value.name === name
</script>
<template>
<RouterLink to="pages/home/home">
<text :class="{ active: isActive('home') }">Home</text>
</RouterLink>
</template>Why custom is not supported
vue-router's custom allows fully custom rendering logic, relying on <a> tags and browser navigation. In uni-app, navigation is driven by the router APIs rather than native components, so fully custom rendering is not supported. To trigger custom navigation, use the useLink() composable to build a custom navigation component (rendering any element you like — on H5 you can render a native <a> to restore link capabilities):
Next Steps
- Router Instance — Programmatic navigation API
- Route Navigation — Deep dive into the four navigation modes
- RouteLocationRaw Type — Type definition of the
toprop - Plugin System — Learn about the plugin registration mechanism
