# When to Use the Vue Router Link Component Instead of Anchor Tags in Vue.js

> Discover when to use Vue Router's `<router-link>` over anchor tags in Vue.js. Leverage client-side routing, state preservation, and navigation guards for seamless internal navigation.

- Repository: [Vue/core](https://github.com/vuejs/core)
- Tags: best-practices
- Published: 2026-02-18

---

**Use `<router-link>` for all internal navigation within your Vue.js single-page application to enable client-side routing, preserve application state, and trigger navigation guards, while reserving standard `<a>` tags strictly for external links or resource downloads.**

In the `vuejs/core` repository, the framework is architected to support seamless SPA navigation through tight integration with Vue Router. The **vue router link component** provides router-aware capabilities that standard anchor tags cannot replicate, making it the idiomatic choice for internal route transitions.

## History API Navigation Without Page Reloads

The `<router-link>` component calls `router.push()` (or `replace`) under the hood, updating the browser URL using the History API without triggering a full page refresh. According to the Vue Router source code, this preserves your application's JavaScript state and provides instantaneous view transitions. A standard `<a href>` tag, by contrast, initiates a standard HTTP request that reloads the entire page, destroying your current component state and re-running all initialization logic.

## Navigation Guards and Route Protection

When you use the vue router link component, navigation guards execute automatically before the route change completes. This includes global guards like `beforeEach` and `beforeResolve`, as well as in-component hooks like `beforeRouteEnter`, `beforeRouteUpdate`, and `beforeRouteLeave`. These guards are essential for authentication checks, data prefetching, and preventing users from losing unsaved form data. Standard anchor tags bypass these guards entirely, allowing navigation to occur regardless of your route protection logic.

## Automatic Active Link Styling

`<router-link>` automatically applies CSS classes to indicate active navigation state. The component adds `router-link-active` when the current route matches the link's target, and `router-link-exact-active` for exact matches. This eliminates the need for custom JavaScript to track the current URL and manually toggle classes. As implemented in [`vuejs/router/src/components/RouterLink.vue`](https://github.com/vuejs/core/blob/main/vuejs/router/src/components/RouterLink.vue), this behavior respects the router's matching logic, including parameters and nested routes.

## Named Routes and Parameter Resolution

The component accepts a `:to` prop that can resolve named routes and parameters dynamically:

```html
<router-link :to="{ name: 'user', params: { id: 42 } }">
  User Profile
</router-link>

```

This allows Vue Router to generate the final URL string based on your route definitions, preventing broken links if paths change later. Standard anchor tags require hardcoded strings that can drift out of sync with your route configuration.

## SSR and Hydration Compatibility

During server-side rendering, `<router-link>` renders as a valid `<a>` tag with the correct `href` attribute, ensuring SEO-friendly markup while preserving SPA navigation behavior once the page hydrates on the client. The Vue Core test suite in [`packages/compiler-sfc/__tests__/compileTemplate.spec.ts`](https://github.com/vuejs/core/blob/main/packages/compiler-sfc/__tests__/compileTemplate.spec.ts) (lines 411-416) specifically verifies SSR handling of router-link components, confirming they render correctly when containing child elements like images.

## Vue Core Integration Points

The vue router link component relies on deep integration with Vue's runtime core. In [`packages/runtime-core/src/componentPublicInstance.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/componentPublicInstance.ts), the framework injects the `$router` instance into every component, allowing `<router-link>` to access routing methods regardless of where it appears in the component tree. Additionally, [`packages/runtime-core/src/component.ts`](https://github.com/vuejs/core/blob/main/packages/runtime-core/src/component.ts) imports `RouterView`, demonstrating the core's expectation of a router-aware rendering outlet that works in tandem with router-link navigation.

## Practical Implementation Examples

### Internal Navigation with router-link

Use `<router-link>` for all application-internal navigation to leverage SPA optimizations:

```html
<template>
  <!-- Basic route navigation -->
  <router-link to="/about">About Us</router-link>
  
  <!-- Named route with parameters -->
  <router-link :to="{ name: 'user', params: { id: 42 } }">
    View User
  </router-link>
  
  <!-- Custom active classes -->
  <nav>
    <router-link to="/" exact-active-class="active-home">Home</router-link>
    <router-link to="/about" active-class="active-page">About</router-link>
  </nav>
</template>

```

### External Links with Standard Anchors

Reserve standard `<a>` tags for external resources where you want default browser behavior:

```html
<a href="https://developer.mozilla.org" target="_blank" rel="noopener">
  MDN Documentation
</a>

```

### Programmatic Navigation Patterns

When combining user interaction with navigation, `<router-link>` maintains proper routing context:

```html
<router-link :to="{ name: 'search' }" @click.prevent="logInteraction">
  Search
</router-link>

<script setup>
import { useRouter } from 'vue-router'

function logInteraction() {
  console.log('Search navigation initiated')
  // Navigation continues via router-link; no manual router.push() needed
}
</script>

```

## When to Use Standard Anchor Tags Instead

Despite the advantages of `<router-link>`, standard anchor tags remain appropriate for specific scenarios:

- **External navigation**: Linking to different domains or websites where you want a full page load
- **File downloads**: Triggering browser download dialogs for PDFs, images, or documents
- **Static HTML sites**: Projects without Vue Router installed where SPA behavior isn't required
- **Email and telephone links**: `mailto:` and `tel:` protocols that don't require routing

## Summary

- **`<router-link>`** is the vue router link component designed specifically for internal SPA navigation, providing History API updates, navigation guards, and automatic active-state styling
- The component integrates deeply with Vue Core through `$router` injection in [`componentPublicInstance.ts`](https://github.com/vuejs/core/blob/main/componentPublicInstance.ts) and coordination with `RouterView`
- **Standard `<a>` tags** trigger full page reloads and should only be used for external links, downloads, or non-SPA contexts
- For SSR applications, `<router-link>` ensures correct hydration while maintaining SEO-friendly markup as verified in the Vue Core test suite

## Frequently Asked Questions

### Does `<router-link>` work with server-side rendering?

Yes, `<router-link>` renders as a standard `<a>` tag with the correct `href` attribute during SSR, ensuring search engines can crawl your links. During client hydration, Vue attaches the SPA navigation behavior. The Vue Core repository includes specific tests in [`packages/compiler-sfc/__tests__/compileTemplate.spec.ts`](https://github.com/vuejs/core/blob/main/packages/compiler-sfc/__tests__/compileTemplate.spec.ts) to verify this SSR compatibility.

### Can I use `<router-link>` for external URLs?

No, `<router-link>` is designed exclusively for internal routes managed by Vue Router. For external websites, use a standard `<a>` tag. Attempting to use `<router-link>` with external URLs will cause routing errors or unexpected behavior since the router cannot resolve those paths.

### How do I style active links with `<router-link>`?

The component automatically applies `router-link-active` and `router-link-exact-active` classes based on the current route. You can customize these class names using the `active-class` and `exact-active-class` props, or configure global defaults in your router configuration. This allows for straightforward CSS styling of navigation states without manual JavaScript tracking.

### What happens if I use a standard anchor tag for internal navigation?

Using `<a>` for internal routes triggers a full browser page refresh, reloading your JavaScript bundle and reinitializing your Vue application. This destroys any client-side state, bypasses navigation guards (including authentication checks), and eliminates the performance benefits of SPA architecture. Always use `<router-link>` for internal navigation to maintain application continuity.