Vue.js: Vue Router

Última atualização: 2026-08-26

O Vue Router é o gerenciador de roteamento oficial do Vue — ele permite que sua SPA (aplicação de página única) tenha várias “páginas”, sendo que cada URL corresponde a um componente. O Vue Router 4 é a versão projetada para o Vue 3 e oferece suporte total à API de Composição.

No cerne do roteamento do SPA está o mapeamento entre URL e componentes. Dominar o Vue Router 4 é uma habilidade essencial para desenvolver qualquer aplicativo Vue que não seja trivial.

1. O que você vai aprender


2. O “pesadelo do 404” de um aplicativo de página única

(1) Problema: 5 páginas, 5 casos de código duplicado

O painel de administração da Alice tinha 5 páginas (Página inicial/Produtos/Pedidos/Usuários/Configurações):

VUE
<!-- ❌ The "Broken" Version: Use v-if to switch 5 components -->
<template>
  <div>
    <button @click="currentPage = 'home'">Home</button>
    <button @click="currentPage = 'products'">Products</button>
    <button @click="currentPage = 'orders'">Orders</button>
    
    <div v-if="currentPage === 'home'"><HomePage /></div>
    <div v-else-if="currentPage === 'products'"><ProductsPage /></div>
    <div v-else-if="currentPage === 'orders'"><OrdersPage /></div>
    <div v-else>Page not found</div>
  </div>
</template>

4 perguntas:

(2) Solução com o Vue Router 4: 5 rotas + 5 componentes

JS
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  { path: '/', component: () => import('@/views/HomePage.vue') },
  { path: '/products', component: () => import('@/views/ProductsPage.vue') },
  { path: '/orders', component: () => import('@/views/OrdersPage.vue') },
  { path: '/users', component: () => import('@/views/UsersPage.vue') },
  { path: '/settings', component: () => import('@/views/SettingsPage.vue') }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router
VUE
<!-- App.vue -->
<template>
  <nav>
    <router-link to="/">Home</router-link>
    <router-link to="/products">Products</router-link>
    <router-link to="/orders">Orders</router-link>
  </nav>
  
  <!-- ✅ Key:router-view Render the component for the current route -->
  <router-view />
</template>

5 rotas + 1 visualização do roteador = um SPA completo. As URLs são sincronizadas automaticamente, e os botões “Avançar” e “Voltar” do navegador funcionam como esperado.

(3) Receita

Depois de usar o Vue Router:


3. Inicialização da rota

(1) Código de inicialização completo

JS
// src/router/index.js
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'

// 1. Define Routes(Lazy Loading)
const routes = [
  { path: '/', component: () => import('@/views/HomePage.vue') },
  { path: '/products', component: () => import('@/views/ProductsPage.vue') }
]

// 2. Create router Examples
const router = createRouter({
  // history Mode: URL without # (Recommended)
  history: createWebHistory(),
  // hash Mode: URL with # (Compatibility with older browsers)
  // history: createWebHashHistory(),
  
  routes,
  
  // Scrolling Behavior:Scroll to the top when switching routes
  scrollBehavior(to, from, savedPosition) {
    return savedPosition || { top: 0 }
  }
})

export default router

(2) Registrando o arquivo main.js

JS
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)  // Registration Routes
app.mount('#app')

(3) Comparação dos dois principais modelos históricos

Aspecto createWebHistory createWebHashHistory
Formato da URL /products /#/products
SEO ✅ Otimizado para SEO ❌ Não otimizado para SEO
Configuração do servidor Obrigatório (try_files) Não obrigatório
Compatibilidade com navegadores IE10+ IE8+
Avaliação ⭐⭐⭐⭐⭐ ⭐⭐

4. 5 tipos de configurações de roteamento

(1) Roteamento estático

JS
const routes = [
  { path: '/', component: () => import('@/views/HomePage.vue') },
  { path: '/about', component: () => import('@/views/AboutPage.vue') },
  { path: '/contact', component: () => import('@/views/ContactPage.vue') }
]

(2) Roteamento dinâmico (parâmetros)

JS
const routes = [
  // /products/123
  { 
    path: '/products/:id', 
    component: () => import('@/views/ProductDetailPage.vue') 
  },
  // /users/456/posts/789
  { 
    path: '/users/:userId/posts/:postId', 
    component: () => import('@/views/PostPage.vue') 
  },
  // Optional Parameters
  { 
    path: '/news/:category?', 
    component: () => import('@/views/NewsPage.vue') 
  }
]
VUE
<!-- ProductDetailPage.vue Receive Parameters -->
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
console.log(route.params.id)  // '123'
</script>

(3) Rotas aninhadas

JS
const routes = [
  {
    path: '/users',
    component: () => import('@/views/UsersPage.vue'),
    children: [
      {
        path: '',  // Default Subroute
        component: () => import('@/views/UsersListPage.vue')
      },
      {
        path: ':id',  // /users/123
        component: () => import('@/views/UserDetailPage.vue')
      }
    ]
  }
]
VUE
<!-- UsersPage.vue -->
<template>
  <div>
    <h1>Users</h1>
    <router-view />  <!-- Subnet Route Outbound -->
  </div>
</template>

(4) Roteamento nomeado

JS
const routes = [
  { 
    path: '/products/:id', 
    name: 'product-detail',  // Named Routing
    component: () => import('@/views/ProductDetailPage.vue') 
  }
]
VUE
<!-- Navigate via name, Avoid hard-coding URL -->
<router-link :to="{ name: 'product-detail', params: { id: 123 } }">
  Product 123
</router-link>

(5) Erro 404 de curinga

JS
const routes = [
  { path: '/', component: () => import('@/views/HomePage.vue') },
  // ... Other Routes
  {
    path: '/:pathMatch(.*)*',  // Match all undefined routes
    component: () => import('@/views/NotFoundPage.vue')
  }
]

5. 5 Tipos de navegação

VUE
<template>
  <!-- String Path -->
  <router-link to="/products">Products</router-link>
  
  <!-- Named Routing(Recommendations) -->
  <router-link :to="{ name: 'products' }">Products</router-link>
  
  <!-- Dynamic Parameters -->
  <router-link :to="{ name: 'product-detail', params: { id: 123 } }">
    Product 123
  </router-link>
  
  <!-- Query Parameters -->
  <router-link :to="{ path: '/search', クエリ: { q: 'vue' } }">
    Search
  </router-link>
</template>

(2) Navegação programática (router.push)

JS
import { useRouter } from 'vue-router'

const router = useRouter()

function goToProduct(id) {
  router.push(`/products/${id}`)  // String
  // or
  router.push({ name: 'product-detail', params: { id } })  // Object
}

function goBack() {
  router.back()  // Back
}

function goForward() {
  router.forward()  // Forward
}

function replaceCurrent() {
  router.replace('/login')  // Replace(Leaving No Trace of History)
}

(3) 5 diferenças entre “push” e “replace”

Método Comportamento Histórico
router.push() Ir para uma nova página Salvar esta página (é possível voltar)
router.replace() Substituir a página atual Não deixar rastros (não é possível voltar)
router.go(n) Avançar/retroceder n passos Ver histórico
router.back() Dê um passo atrás Explore a história
router.forward() Dê um passo à frente Percorra a história

(4) Comparação entre programação procedural e declarativa

Cenário Recomendação
O usuário clica no link router-link (declarativo)
Navegação acionada por JS router.push (programaticamente)
Redirecionar após o envio do formulário router.push
Redirecionar após o login router.replace
Redirecionamento automático 404 router.back

6. Route Guard (Navigation Guard)

(1) 3 tipos de guardas

JS
// 1. Global Frontline Guard(Most Commonly Used)
router.beforeEach((to, from, next) => {
  const isLoggedIn = !!localStorage.getItem('token')
  
  if (to.meta.requiresAuth && !isLoggedIn) {
    next('/login')  // Skip Login
  } else {
    next()  // Clearance
  }
})

// 2. Dedicated Route Guard
const routes = [
  {
    path: '/admin',
    component: () => import('@/views/AdminPage.vue'),
    beforeEnter: (to, from, next) => {
      if (isAdmin()) next()
      else next('/403')
    }
  }
]

// 3. In-Component Guard
// Within the component:beforeRouteEnter / beforeRouteUpdate / beforeRouteLeave

(2) Exemplo completo de proteção de login

JS
// router/index.js
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token')
  const isLoggedIn = !!token
  
  // Pages that require login
  if (to.meta.requiresAuth && !isLoggedIn) {
    return next({ 
      name: 'login', 
      クエリ: { redirect: to.fullPath }  // Redirect after logging in
    })
  }
  
  // Already logged in. Go to the login page.
  if (to.name === 'login' && isLoggedIn) {
    return next({ name: 'home' })
  }
  
  next()
})
▶ Experimente
JS
// Routing meta Layout
const routes = [
  {
    path: '/dashboard',
    component: () => import('@/views/DashboardPage.vue'),
    meta: { requiresAuth: true }  // You must log in
  }
]

7. Exemplo completo: Sistema de roteamento de back-end para comércio eletrônico

▶ Exemplo: 1. 5 tipos de configurações de roteamento

JS
const routes = [
  // 1. Static Routing
  { path: '/', name: 'home', component: () => import('@/views/HomePage.vue') },
  
  // 2. Dynamic Routing
  { 
    path: '/products/:id', 
    name: 'product-detail',
    component: () => import('@/views/ProductDetailPage.vue') 
  },
  
  // 3. Nested Routes
  {
    path: '/admin',
    component: () => import('@/views/AdminLayout.vue'),
    meta: { requiresAuth: true },
    children: [
      { path: '', name: 'admin-dashboard', component: () => import('@/views/DashboardPage.vue') },
      { path: 'products', name: 'admin-products', component: () => import('@/views/AdminProductsPage.vue') },
      { path: 'orders', name: 'admin-orders', component: () => import('@/views/AdminOrdersPage.vue') }
    ]
  },
  
  // 4. Named Routing
  { 
    path: '/user/:userId', 
    name: 'user-profile',
    component: () => import('@/views/UserProfilePage.vue') 
  },
  
  // 5. 404
  { path: '/:pathMatch(.*)*', name: 'not-found', component: () => import('@/views/NotFoundPage.vue') }
]
▶ Experimente

▶ Exemplo: 2. Carregamento diferido de rotas (carregamento sob demanda de 5 componentes)

JS
const routes = [
  // ✅ Recommendations:News import
  { path: '/', component: () => import('@/views/HomePage.vue') },
  { path: '/products', component: () => import('@/views/ProductsPage.vue') }
]
▶ Experimente

▶ Exemplo: 3. 5 Tipos de navegação

VUE
<!-- 1. String Path -->
<router-link to="/products">Products</router-link>

<!-- 2. Named Routing(Recommendations)-->
<router-link :to="{ name: 'products' }">Products</router-link>

<!-- 3. Dynamic Parameters -->
<router-link :to="{ name: 'product-detail', params: { id: 123 } }">
  Product 123
</router-link>

<!-- 4. Query Parameters -->
<router-link :to="{ path: '/search', query: { q: 'vue' } }">
  Search
</router-link>

<!-- 5. Programmatic Navigation -->
<button @click="goToProduct(123)">Go to Product</button>
▶ Experimente
JS
import { useRouter } from 'vue-router'
const router = useRouter()
function goToProduct(id) {
  router.push({ name: 'product-detail', params: { id } })
}

▶ Exemplo: 4. Completar o Login Guard

JS
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token')
  const isLoggedIn = !!token
  
  if (to.meta.requiresAuth && !isLoggedIn) {
    return next({ name: 'login', クエリ: { redirect: to.fullPath } })
  }
  
  if (to.name === 'login' && isLoggedIn) {
    return next({ name: 'home' })
  }
  
  next()
})
▶ Experimente

▶ Exemplo: 5. Referência rápida para 5 erros comuns

Erro Sintoma Solução
falta a visualização do roteador Página não exibida Adicionar <router-view />
As rotas não são carregadas de forma diferida Carregamento lento da primeira tela Use () => import() para importação dinâmica
Loop infinito Não é possível sair Impedir que o next() acione o beforeEach novamente
Roteamento aninhado sem saída Subpágina não exibida Adicionar <router-view /> ao componente pai
404 Rota não encontrada Erro Adicionar path: '/:pathMatch(.*)*'

▶ Exemplo: 6. 5 Principais comparações de desempenho

Modo Primeira tela Botão Aplicável
Importação estática Lenta Rápida Projetos pequenos
Importação dinâmica ⭐⭐⭐⭐⭐ Lenta no primeiro carregamento Recomendado
Carregamento diferido de grupos de roteamento ⭐⭐⭐⭐⭐ Lento no primeiro carregamento Projetos grandes
pré-busca ⭐⭐⭐⭐ Rápido Prioridade à experiência do usuário
SSR ⭐⭐⭐⭐⭐ Rápido Nuxt 3

❓ Perguntas Frequentes

P: O que devo escolher, createWebHistory ou createWebHashHistory? R: createWebHistory (URLs sem #, otimizadas para SEO) requer configuração do servidor; createWebHashHistory (URLs com #) é compatível com navegadores mais antigos. createWebHistory é recomendado para ambientes de produção.

P: Como o roteamento dinâmico recebe parâmetros? R: Use o gancho useRoute(): const route = useRoute(); route.params.id.

P: Qual é a diferença entre router.push e router.replace? R: push adiciona a página ao histórico do navegador (permitindo que os usuários voltem), enquanto replace substitui a página atual (sem deixar rastros no histórico). Use replace após o login (já que os usuários não podem voltar à página de login).

P: O router guard pode ser executado de forma assíncrona? R: Sim. beforeEach(async (to, from, next) => { await checkAuth(); next() }). Mas tome cuidado para evitar loops infinitos.

P: Como se implementa o roteamento aninhado? R: Configure a rota filha na rota pai usando children: [] e adicione <router-view /> ao modelo do componente pai como ponto de saída para a rota filha.

P: Quais são as diferenças entre o Vue Router 4 e o Vue Router 3? R: O Vue Router 4 é compatível com a Composition API (useRouter/useRoute), oferece uma inferência de tipos mais robusta no TypeScript e alterou os parâmetros do navigation guard (to/from/next). Os projetos do Vue 3 devem usar o Vue Router 4.

P: Em que medida o carregamento diferido melhora o desempenho? R: Ele pode reduzir o tempo de carregamento da primeira tela em 50 a 80% (ao não carregar páginas que ainda não foram visitadas). O efeito é particularmente perceptível em projetos grandes (mais de 10 páginas).

P: Como faço para usar os metacampos nos guardas de rota? R: Adicione meta: { requiresAuth: true } à configuração da rota e use to.meta.requiresAuth no guarda. Eles são usados para permissões, títulos, trilhas de navegação e muito mais.


📖 Resumo


📝 Exercícios

  1. Questões básicas (Dificuldade: ⭐)

    Implementar uma SPA simples com várias páginas:

    • 3 páginas: Página inicial / Sobre nós / Contato
    • Navegação superior + visualização do router na parte inferior
    • Configure o roteador usando vue-router
  2. Problemas avançados (Dificuldade: ⭐⭐)

    Implementação do roteamento de produtos no comércio eletrônico:

    • /products Página de lista
    • /products/:id Página de detalhes (parâmetros dinâmicos)
    • /products/:id/edit Editar página
    • Tratamento do erro 404
  3. Problema desafiador (Dificuldade: ⭐⭐⭐)

    Implementar um sistema completo de roteamento de back-end para comércio eletrônico:

    1. Mais de 10 páginas (página inicial/produtos/pedidos/usuários/configurações/login/404 etc.)
    2. Rotas aninhadas (/admin/dashboard, /admin/products etc.)
    3. Carregamento diferido de rotas (carregamento mais rápido da primeira tela)
    4. Faça login como guarda (se ainda não estiver conectado, acesse /login; se já estiver conectado, volte a esta página)
    5. Abordagem abrangente de 5 métodos de navegação
    6. Navegação programática (Clique no botão para navegar)
    7. Configuração de rotas com tipagem forte no TypeScript
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%