Vue Router Documentation

website·Indexed 18 days ago

https://router.vuejs.org/

Official routing solution for Vue.js, covering client-side routing, file-based routing, and data loaders. Includes guides on navigation guards, dynamic route matching, lazy loading, and migration paths from Vue Router v3 to v4 and v4 to v5. Features documentation for data fetching utilities like defineBasicLoader() and defineColadaLoader(), as well as experimental features like custom param parsers.

Tokens
31.2K
Snippets
199
Records
229
Agent score
98%

What's inside Vue Router

  1. Overview of Vue Router features

    Vue Router is the official router for Vue.js, designed for building Single Page Applications (SPAs). It integrates deeply with the Vue.js core and provides the following capabilities:

    • Nested routes mapping and dynamic routing
    • Modular, component-based router configuration
    • Support for route parameters, queries, and wildcards
    • View transition effects using the Vue.js transition system
    • Fine-grained navigation control
    • Automatic active CSS classes for links
    • Support for both HTML5 history mode and hash mode
    • Customizable scroll behavior
    • Proper URL encoding
  2. Overview of Vue Router Data Loaders

    Data Loaders integrate data fetching directly into the Vue Router navigation cycle. They provide several key benefits: navigation is blocked until data is fetched (unless marked as lazy), requests are deduplicated, and data updates are delayed until all loaders resolve to avoid inconsistent UI states. This approach avoids the need for <Suspense> and cascading loading states. While implemented under unplugin-vue-router to enable better typing, the feature is independent and works without file-based routing.
  3. Configure ESLint for vue-router auto-routes imports

    If you are not using auto imports, you must explicitly tell ESLint about the vue-router/auto-routes module to avoid import errors. This is done by adding it to the import/core-modules setting in your ESLint configuration.
    {
      "settings": {
        "import/core-modules": ["vue-router/auto-routes"]
      }
    }
  4. Handle errors in Vue Router Data Loaders

    By default, errors thrown in a loader are treated as 'unexpected errors'. They abort the navigation and are intercepted by router.onError(), meaning they will not appear in the loader's error property. However, if a loader is not navigation-aware (such as lazy loaders or during data reloading), the error is not intercepted by Vue Router and is instead stored in the loader's error property.
  5. Implement Typed Routes in Vue Router

    Typed Routes allow for a map of routes that provides autocompletion and type safety for route names and parameters when using router.push() or the to prop in RouterLink. While this can be configured manually, it is highly recommended to use the built-in file-based routing plugin to generate these types automatically.
  6. Understand basic file-based routing structure

    By default, the plugin scans src/pages for .vue files to generate routes. File names map directly to URL paths. Files named index.vue (must be lowercase) act as the root for their respective directory.
    src/pages/
    ├── index.vue       -> /
    ├── about.vue       -> /about
    └── users/
        ├── index.vue  -> /users
        └── [id].vue    -> /users/:id
  7. Remove legacy unplugin-vue-router client types

    Remove references to unplugin-vue-router/client from env.d.ts or tsconfig.json as they are no longer needed in Vue Router 5.
    // Remove from env.d.ts
    /// <reference types="unplugin-vue-router/client" />
    // Remove from tsconfig.json include array
    "include": [
      "unplugin-vue-router/client"
    ]
  8. Create nested routes with layouts

    To create a nested route where a child component is rendered inside a parent's <RouterView>, define a .vue file and a folder with the same name. For example, users.vue acts as the parent layout, and users/index.vue acts as the child route.
    src/pages/
    ├── users.vue       // Parent layout
    └── users/
        └── index.vue   // Child route (renders inside users.vue)
  9. Define optional route parameters

    Mark a parameter as optional using the ? modifier (0 or 1 occurrence). If a route segment contains more than just an optional parameter (e.g., static text or multiple optional params), the route will not match a path without a trailing slash.
    const routes = [
      // matches /users and /users/posva
      { path: '/users/:userId?' },
      // matches /users and /users/42 (numeric only)
      { path: '/users/:userId(\\d+)?' },
    ]
  10. Define a basic data loader using defineBasicLoader

    Data loaders are composables created via defineLoader functions (such as defineBasicLoader). They are asynchronous functions that fetch data based on the target route. The returned composable provides the fetched data, loading state, error state, and a reload function.
    <script lang="ts">
    import { defineBasicLoader } from 'vue-router/experimental'
    import { getUserById } from '../api'
    
    export const useUserData = defineBasicLoader('/users/[id]', async to => {
      return getUserById(to.params.id)
    })
    </script>
    
    <script setup lang="ts">
    const {
      data: user, // the data returned by the loader
      isLoading, // boolean indicating if the loader is fetching
      error, // error object if the loader failed
      reload, // function to refetch data without navigating
    } = useUserData()
    </script>
  11. Handle nested Data Loaders and async context

    When using nested loaders, you must call and await all nested loaders at the top of the parent loader. You cannot place a regular await (for a non-loader promise) between them. If you must await a non-loader promise in between, wrap it with withContext() to ensure the loader context is properly restored and nested loaders remain aware of their parent.
    export const useUserCommonFriends = defineLoader(async (route) => {
      const user = await useUserData()
      // Wrap non-loader promises with withContext
      await withContext(functionThatReturnsAPromise())
      const me = await useCurrentUserData()
    
      // ...
    })
  12. Control navigation from a Data Loader

    Because data fetching occurs within navigation guards, loaders can control the navigation flow using NavigationResult.

    • Redirect/Cancel: Return new NavigationResult(targetLocation) to redirect, or new NavigationResult(false) to cancel.
    • Resolved Data: Any value returned that is not a NavigationResult is treated as the resolved data.
    • Abort: Throwing a standard error or rejecting a promise cancels the navigation and triggers router.onError().
    • Eager Alteration: Throwing a NavigationResult (instead of returning it) skips the selectNavigationResult logic and takes immediate precedence.
    import { NavigationResult } from 'vue-router'
    
    export const useUserData = defineLoader(
      async (to) => {
        try {
          const user = await getUserById(to.params.id)
          return user
        } catch (error) {
          if (error.status === 404) {
            // Redirect to not-found page
            return new NavigationResult({ name: 'not-found', params: { pathMatch: '' } })
          } else {
            throw error // Aborts navigation and triggers router.onError()
          }
        }
      }
    )