Vue.js: Vue Router
Última atualização: 2026-10-20
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
- Inicialização do createRouter + createWebHistory
- 5 tipos de rotas: estáticas, dinâmicas, aninhadas, nomeadas e com curinga
- Navegação programática (router.push / replace / go)
- Carregamento diferido de rotas (importação dinâmica)
- Parâmetros de rota (params / consulta)
- Guarda-rotas (beforeEach / beforeEnter)
- 5 cenários-chave do mundo real
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):
4 perguntas:
- A URL permanece inalterada: ao atualizar a página, a página atual é perdida
- Sem link para compartilhamento: Não é possível copiar a URL para compartilhar com colegas
- Ausência dos botões “Avançar” e “Voltar” do navegador: Experiência do usuário insatisfatória
- SEO inadequado: os mecanismos de busca não conseguem interpretá-lo
(2) Solução com o Vue Router 4: 5 rotas + 5 componentes
// 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
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:
- Sincronização de URL: Sincronização automática; atualiza os dados sem perder os já existentes
- Compartilhável: Cada página tem uma URL
- Histórico do navegador: os botões “Avançar” e “Voltar” funcionam conforme o esperado
- Otimizado para SEO: suporte a SSR (Nuxt 3)
- Volume de código: 5 diretivas v-if → 5 linhas na matriz de rotas (-80%)
3. Inicialização da rota
(1) Código de inicialização completo
// 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
(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
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)
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')
}
]
<!-- ProductDetailPage.vue Receive Parameters -->
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.id) // '123'
</script>
(3) Rotas aninhadas
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')
}
]
}
]
(4) Roteamento nomeado
const routes = [
{
path: '/products/:id',
name: 'product-detail', // Named Routing
component: () => import('@/views/ProductDetailPage.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
const routes = [
{ path: '/', component: () => import('@/views/HomePage.vue') },
// ... Other Routes
{
path: '/:pathMatch(.*)*', // Match all undefined routes
component: () => import('@/views/NotFoundPage.vue')
}
]
▶ Exemplo: 5 tipos de configurações de roteamento
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') }
]
Saída:
/ abre HomePage; /products/42 abre o detalhe com route.params.id = 42.
/admin/products renderiza o filho dentro do AdminLayout (router-view aninhado).
Qualquer caminho inexistente cai em NotFoundPage pela rota curinga.
▶ Exemplo: Carregamento diferido de rotas (carregamento sob demanda de 5 componentes)
const routes = [
// ✅ Recommendations:News import
{ path: '/', component: () => import('@/views/HomePage.vue') },
{ path: '/products', component: () => import('@/views/ProductsPage.vue') }
]
Saída:
Cada rota vira um arquivo JS separado no build.
A primeira tela baixa só o chunk da HomePage.
Ao visitar /products, o chunk ProductsPage é baixado naquele momento.
5. 5 Tipos de navegação
(1) Navegação declarativa (router-link)
(2) Navegação programática (router.push)
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 |
▶ Exemplo: 5 Tipos de navegação
<!-- 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>
import { useRouter } from 'vue-router'
const router = useRouter()
function goToProduct(id) {
router.push({ name: 'product-detail', params: { id } })
}
Saída:
Clicar em Products leva a /products; a versão com name usa a rota nomeada.
O link com params gera /product/123 e o de query gera /search?q=vue.
O botão dispara router.push e o histórico registra a nova entrada.
6. Route Guard (Navigation Guard)
(1) 3 tipos de guardas
// 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
// 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',
query: { 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()
})
// Routing meta Layout
const routes = [
{
path: '/dashboard',
component: () => import('@/views/DashboardPage.vue'),
meta: { requiresAuth: true } // You must log in
}
]
7. Exercício abrangente: guarda de navegação de login
▶ Exemplo: Completar o Login Guard
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
const isLoggedIn = !!token
if (to.meta.requiresAuth && !isLoggedIn) {
return next({ name: 'login', query: { redirect: to.fullPath } })
}
if (to.name === 'login' && isLoggedIn) {
return next({ name: 'home' })
}
next()
})
Saída:
Sem token, acessar /admin redireciona para /login?redirect=/admin.
Depois do login, o usuário volta para a rota original.
Já logado, acessar /login leva direto para a home.
(1) 📊 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(.*)*' |
(2) 📊 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
createWebHistory ou createWebHashHistory?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.useRoute(): const route = useRoute(); route.params.id.router.push e router.replace?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).beforeEach(async (to, from, next) => { await checkAuth(); next() }). Mas tome cuidado para evitar loops infinitos.children: [] e adicione <router-view /> ao modelo do componente pai como ponto de saída para a rota filha.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
- O Vue Router 4 é o gerenciador de roteamento oficial do Vue 3
- 5 tipos de rotas: estáticas, dinâmicas, aninhadas, nomeadas e com curinga
- 5 tipos de navegação: router-link, router.push, replace, back, forward
- 3 tipos de observadores: global (beforeEach), específico da rota (beforeEnter) e interno ao componente
- O carregamento diferido de rotas (importações dinâmicas) reduz o tempo até a primeira visualização
- Recomenda-se usar
createWebHistory;createWebHashHistoryserve para garantir a compatibilidade com navegadores mais antigos - Rotas aninhadas com filhos +
<router-view />
📝 Exercícios
-
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
-
Problemas avançados (Dificuldade: ⭐⭐)
Implementação do roteamento de produtos no comércio eletrônico:
/productsPágina de lista/products/:idPágina de detalhes (parâmetros dinâmicos)/products/:id/editEditar página- Tratamento do erro 404
-
Problema desafiador (Dificuldade: ⭐⭐⭐)
Implementar um sistema completo de roteamento de back-end para comércio eletrônico:
- Mais de 10 páginas (página inicial/produtos/pedidos/usuários/configurações/login/404 etc.)
- Rotas aninhadas (/admin/dashboard, /admin/products etc.)
- Carregamento diferido de rotas (carregamento mais rápido da primeira tela)
- Faça login como guarda (se ainda não estiver conectado, acesse /login; se já estiver conectado, volte a esta página)
- Abordagem abrangente de 5 métodos de navegação
- Navegação programática (Clique no botão para navegar)
- Configuração de rotas com tipagem forte no TypeScript