# How to Ensure Your Vue Router Link Navigates to the Correct Component

> Master Vue Router navigation. Learn to ensure your Vue Router link correctly directs users to the intended component by following these essential setup steps.

- Repository: [Vue/core](https://github.com/vuejs/core)
- Tags: how-to-guide
- Published: 2026-02-16

---

**To ensure your Vue Router link navigates correctly, you must register the router instance with `app.use(router)`, define route records that map paths to components, and use the `to` prop with either a string path or location object.**

When a user clicks a `<router-link>` in a Vue.js application, the framework must resolve that navigation intent to a specific component instance. According to the `vuejs/core` source code, this resolution depends on Vue’s internal `resolveComponent` helper and the global registration of router components. Understanding this mechanism ensures your **vue router link navigates** to the intended view every time.

## How Vue Router Link Resolution Works

Vue Router relies on Vue’s component resolution system to transform `<router-link>` and `<router-view>` tags into actual component instances. When you install Vue Router using `app.use(router)`, the plugin globally registers `RouterLink` and `RouterView` components.

As implemented in [`packages/runtime-core/src/helpers/resolveAssets.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/helpers/resolveAssets.ts) (lines 22-27), Vue’s `resolveComponent` helper searches for components in the current instance’s **local** registrations first, then falls back to **global** registrations. This is why `app.use(router)` is critical—it ensures `resolveComponent` can find the router components when parsing your templates.

## Step-by-Step: Configuring Vue Router for Correct Navigation

### 1. Create and Register the Router Instance

Before any **vue router link navigates** successfully, you must create a router instance and install it on the Vue application. This step globally registers the `<router-link>` and `<router-view>` components.

```typescript
// main.ts
import { createApp } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import App from './App.vue'

const router = createRouter({
  history: createWebHistory(),
  routes: [] // defined in next step
})

const app = createApp(App)
app.use(router) // Globally registers RouterLink and RouterView
app.mount('#app')

```

As shown in [`packages/runtime-core/src/componentPublicInstance.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/componentPublicInstance.ts) (lines 62-78), this installation process attaches the router instance to all component instances, enabling access to `$router` and `$route` properties.

### 2. Define Route Records with Component Mappings

Route records establish the connection between URLs and components. You can use **eager loading** (static imports) or **lazy loading** (dynamic imports) for your components.

```typescript
// router configuration
const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'home',
      component: () => import('./components/Home.vue') // Lazy-loaded
    },
    {
      path: '/about',
      name: 'about',
      component: () => import('./components/About.vue')
    },
    {
      path: '/profile/:id',
      name: 'profile',
      component: () => import('./components/Profile.vue')
    }
  ]
})

```

Vue normalizes component names using `camelize` and `capitalize` helpers during registration. Ensure your route record component names match the registered names exactly to avoid resolution failures.

### 3. Use Router Link with Valid To Prop Values

The `to` prop accepts either a **string path** or a **location object**. Using named routes with location objects makes your links more maintainable.

```vue
<!-- App.vue -->
<template>
  <nav>
    <!-- String path -->
    <router-link to="/">Home</router-link>
    
    <!-- Named route with params -->
    <router-link :to="{ name: 'profile', params: { id: '123' } }">
      User Profile
    </router-link>
    
    <!-- Named route with query -->
    <router-link :to="{ name: 'about', query: { section: 'team' } }">
      About Us
    </router-link>
  </nav>

  <!-- Component outlet -->
  <router-view />
</template>

```

When clicked, the `<router-link>` component calls the router's `push` method with the resolved location, triggering the navigation flow.

### 4. Render Components with Router View

The `<router-view>` component acts as the outlet for matched components. Vue resolves this component through the same `resolveComponent` mechanism used for `router-link`.

As defined in [`packages/runtime-core/src/component.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/component.ts) (lines 165-171), global component registrations are stored on the app context. When the route changes, `<router-view>` retrieves the matched component from the route record and renders it, swapping instances as the navigation history changes.

## Understanding Component Resolution in Vue Core

Vue's component resolution system ensures that `<router-link>` and `<router-view>` are correctly instantiated. The `resolveComponent` helper in [`packages/runtime-core/src/helpers/resolveAssets.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/helpers/resolveAssets.ts) performs a hierarchical lookup:

1. **Local registration**: Checks `components` option on the current instance
2. **Global registration**: Checks `appContext.components` (populated by `app.use(router)`)
3. **Warning**: If not found, Vue warns about unresolved components

This resolution chain explains why installing the router before mounting the app is mandatory. Without `app.use(router)`, the `RouterLink` and `RouterView` components remain unregistered, causing `resolveComponent` to fail when parsing templates containing these tags.

## Troubleshooting Navigation Failures

If your **vue router link navigates** to the wrong component or fails to render:

- **Verify global registration**: Ensure `app.use(router)` is called before `app.mount()`. Check that you're using the correct router instance created with `createRouter`.
- **Check route record matching**: Confirm the `path` or `name` in your `to` prop exactly matches a defined route. Remember that `params` must be defined in the route path (`:id`) to work with named routes.
- **Validate component availability**: For lazy-loaded routes, ensure the import path is correct. For eager loading, verify the component is imported and assigned to the route record.
- **Inspect component names**: Vue normalizes component names during registration. If using string templates, ensure case sensitivity matches the registration (PascalCase vs kebab-case).

## Summary

- **Global registration is mandatory**: Call `app.use(router)` to register `<router-link>` and `<router-view>` globally, enabling Vue's `resolveComponent` helper to find them.
- **Route records map URLs to components**: Define paths and components (eager or lazy-loaded) in the router configuration to establish navigation targets.
- **Use valid `to` prop values**: Pass string paths or location objects with correct names and params to `<router-link>`.
- **Render with `<router-view>`**: Place this outlet component where matched route components should display.
- **Resolution follows hierarchy**: Vue checks local then global registrations via [`packages/runtime-core/src/helpers/resolveAssets.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/helpers/resolveAssets.ts).

## Frequently Asked Questions

### Why does my router-link render as plain text instead of a link?

This occurs when Vue cannot resolve the `<router-link>` component, usually because `app.use(router)` was not called before mounting the application. Without global registration, Vue's `resolveComponent` helper (located in [`packages/runtime-core/src/helpers/resolveAssets.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/helpers/resolveAssets.ts)) fails to find the `RouterLink` definition, treating the tag as an unknown custom element.

### Can I use router-link without globally registering the router?

No. While you can manually import `RouterLink` from `vue-router` and register it locally in a component, standard Vue Router usage requires global registration via `app.use(router)`. This installation process registers both `RouterLink` and `RouterView` on the application context, ensuring they are available to `resolveComponent` throughout the component tree.

### What happens if the to prop points to a non-existent route?

If the `to` prop references a path or name not defined in your route records, Vue Router will still push the location to the history, but `<router-view>` will have no matched component to render. Depending on your router configuration, this may render nothing, show a fallback component (if you have a catch-all `/*` route), or trigger navigation guards that handle the 404 scenario.

### How does Vue distinguish between local and global component registrations?

Vue checks local registrations first by looking at the `components` option on the current component instance. If not found, it falls back to `appContext.components` (global registrations) as implemented in [`packages/runtime-core/src/helpers/resolveAssets.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/helpers/resolveAssets.ts). This hierarchical lookup means local components shadow global ones, but global registrations (like those created by `app.use(router)`) serve as the default for standard router components.