404 Not Found

404 Not Found


nginx

Páginas e Rotas

Ao adicionar páginas de detalhes de produtos à MegaShop, Bob configurou manualmente 50 rotas vue-router. Toda vez que um novo produto era listado, ele tinha que editar os arquivos de rota—era uma dor de cabeça. Charlie disse a ele que o Nuxt 3 gera rotas automaticamente com base em convenções de arquivos, então criar um arquivo é o mesmo que criar uma rota.

1. O Que Você Vai Aprender


2. Uma História Real de um Administrador

(1) Dor: O Pesadelo da Configuração Manual de Rotas

Bob configurou 1.000 rotas para a MegaShop usando o Vue Router tradicional—uma para cada categoria e cada página de produto. Toda vez que um novo produto era listado, ele tinha que editar o arquivo de rotas; se esquecesse de um, o resultado era um erro 404. Alice não conseguia encontrar os produtos, e a taxa de reclamações disparou.

(2) Solução com Roteamento por Arquivos do Nuxt

Com o roteamento baseado em arquivos do Nuxt 3, Bob só precisa criar um arquivo:

TEXT
pages/products/[id].vue  →  /products/:id

Um milhão de produtos em um único arquivo, com parâmetros dinâmicos passados automaticamente.

(3) Benefícios: Roteamento Zero-Config

Bob não precisa mais escrever configurações de rotas—adicionar uma nova página é tão simples quanto criar um novo arquivo, e 1 milhão de páginas de detalhes de produtos requerem apenas um [id].vue.


3. Regras de Roteamento por Arquivos

(1) Processo de Mapeamento de Diretório para Rota

100%
flowchart LR
    A[pages/index.vue] -->|"/"| B[Rota Raiz]
    C[pages/about.vue] -->|"/about"| C2[Rota About]
    D[pages/products/index.vue] -->|"/products"| D2[Rota Lista de Produtos]
    E[pages/products/[id].vue] -->|"/products/:id"| E2[Rota Detalhe do Produto]
    F[pages/categories/[...slug].vue] -->|"/categories/:slug*"| F2[Rota Catch-all]

(2) Regras de Mapeamento de Roteamento por Arquivos

Caminho do Arquivo Rota Gerada Descrição
pages/index.vue / Home
pages/about.vue /about Página estática
pages/products/index.vue /products Lista de Produtos
pages/products/[id].vue /products/:id Parâmetro Dinâmico
pages/categories/[slug].vue /categories/:slug Parâmetros Dinâmicos
pages/categories/[...slug].vue /categories/:slug(*) Rota curinga
pages/404.vue /404 404 Personalizado

(1) ▶Exemplo: Roteamento Básico de Página

VUE
<!-- pages/index.vue -->
<template>
  <div>
    <h1>MegaShop - Milhões de Produtos</h1>
    <NuxtLink to="/products">Navegar Produtos</NuxtLink>
  </div>
</template>

Saída:

TEXT
// Execução Bem-sucedida
VUE
<!-- pages/about.vue -->
<template>
  <div>
    <h1>Sobre a MegaShop</h1>
    <p>Atendendo mais de 1 milhão de produtos mundialmente</p>
  </div>
</template>

4. Rotas Dinâmicas

(1) Rota Dinâmica com Parâmetro Único

Use a sintaxe [param] para definir parâmetros de rota dinâmica.

(1) ▶Exemplo: Rota Dinâmica para Páginas de Detalhes de Produtos

VUE
<!-- pages/products/[id].vue -->
<template>
  <div>
    <h1>Produto #{{ route.params.id }}</h1>
    <p>Preço: ${{ product?.price }} USD</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
</script>

Saída:

TEXT
// Execução Bem-sucedida

(2) Rotas Curinga

Use a sintaxe [...slug] para capturar caminhos multi-nível.

(2) ▶Exemplo: Rota Curinga de Categorias Multi-Nível

VUE
<!-- pages/categories/[...slug].vue -->
<template>
  <div>
    <h1>Categoria: {{ slugPath }}</h1>
    <p>{{ products.length }} produtos encontrados</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
// /categories/electronics/headphones → slug = ['electronics', 'headphones']
const slugPath = computed(() => (route.params.slug as string[]).join('/'))
const { data: products } = await useFetch(`/api/categories/${slugPath.value}`)
</script>

Saída:

TEXT
// Execução Bem-sucedida

(3) Tipos de Parâmetros de Rotas Dinâmicas

Sintaxe Correspondência URL de Exemplo Valor de params
[id] Segmento único /products/123 { id: '123' }
[id].vue + index.vue Opcional /products ou /products/123 { id?: '123' }
[...slug] Curinga multi-segmento /a/b/c { slug: ['a','b','c'] }

5. Rotas Aninhadas

(1) Estrutura de Rotas Aninhadas

Rotas aninhadas requerem uma página pai (um arquivo .vue com o mesmo nome) e um diretório filho trabalhando juntos:

TEXT
pages/
├── products/
│   ├── index.vue          # /products (filho)
│   ├── [id].vue           # /products/:id (filho)
│   └── edit.vue           # /products/edit (filho)
└── products.vue           # /products (pai com <NuxtPage />)

(1) ▶Exemplo: Rotas Aninhadas na Página de Produtos

VUE
<!-- pages/products.vue - Layout pai -->
<template>
  <div>
    <nav class="product-nav">
      <NuxtLink to="/products">Todos os Produtos</NuxtLink>
      <NuxtLink to="/products/featured">Destaques</NuxtLink>
    </nav>
    <!-- Rotas filhas renderizam aqui -->
    <NuxtPage />
  </div>
</template>

Saída:

TEXT
// Execução Bem-sucedida
VUE
<!-- pages/products/index.vue - Filho: lista de produtos -->
<template>
  <div>
    <h1>Todos os Produtos</h1>
    <p>1 milhão de produtos disponíveis</p>
  </div>
</template>
VUE
<!-- pages/products/[id].vue - Filho: detalhe do produto -->
<template>
  <div>
    <h1>Detalhe do Produto</h1>
    <p>ID: {{ route.params.id }}</p>
  </div>
</template>

(2) Comparação de Rotas Aninhadas vs. Layout

Dimensão Rotas Aninhadas Layout
Mecanismo Página pai + slot NuxtPage layouts/ + NuxtLayout
Relacionamento de Rotas Rotas Pai-Filho Compartilhando Layouts Troca de Layout em Nível de Página
Recuperação de Dados Pai e filho cada um usa useFetch Layout não busca dados
Casos de Uso Hierarquia Categoria → Produto → Review Layout Geral de Página (Header/Footer)

6. Navegação Programática

(1) Comparação de Três Métodos de Navegação

API Propósito Disponível no Servidor Caso de Uso
navigateTo() Navegação programática Redirecionamento após login
useRouter().push() Navegação no lado do cliente Navegação via clique de botão
NuxtLink Links Declarativos Navegação em Templates

(1) ▶Exemplo: Redirecionamento no Lado do Servidor com navigateTo

TYPESCRIPT
// No middleware ou contexto do lado do servidor
export default defineNuxtRouteMiddleware((to) => {
  const isAuthenticated = useState('isAuthenticated')

  if (!isAuthenticated.value && to.path.startsWith('/admin')) {
    return navigateTo('/login', { redirectCode: 302 })
  }
})

Saída:

TEXT
// Execução Bem-sucedida

(2) ▶Exemplo: Navegação no lado do cliente com useRouter

VUE
<template>
  <button @click="goToProduct(product.id)">
    Ver Detalhes
  </button>
</template>

<script setup lang="ts">
const router = useRouter()

function goToProduct(id: number) {
  router.push(`/products/${id}`)
}
</script>

Saída:

TEXT
// Execução Bem-sucedida

(3) ▶Exemplo: Obtendo parâmetros com useRoute

VUE
<script setup lang="ts">
const route = useRoute()

// Acessar params
const productId = route.params.id         // De [id].vue
const categorySlug = route.params.slug     // De [...slug].vue

// Acessar query params
// /products?category=electronics&sort=price
const category = route.query.category      // 'electronics'
const sort = route.query.sort              // 'price'
</script>

Saída:

TEXT
// Execução Bem-sucedida

7. Guia Prático de Rotas Multi-Nível na MegaShop

(1) Plano de Rotas da MegaShop

URL Arquivo Função
/ pages/index.vue Home
/products pages/products/index.vue Lista de Produtos
/products/[id] pages/products/[id].vue Detalhes do Produto
/categories/[category] pages/categories/[category].vue Página de Categoria
/categories/[category]/[subcategory] pages/categories/[...slug].vue Subcategoria
/cart pages/cart.vue Carrinho de Compras
/checkout pages/checkout.vue Página de Checkout
/admin pages/admin/index.vue Painel de Administração
/admin/products pages/admin/products/index.vue Gestão de Produtos
/404 pages/404.vue Página 404

(1) ▶Exemplo: Página 404 da MegaShop

VUE
<!-- pages/404.vue -->
<template>
  <div class="not-found">
    <h1>404 - Produto Não Encontrado</h1>
    <p>O produto que você está procurando não existe.</p>
    <NuxtLink to="/products">Navegar todos os produtos</NuxtLink>
  </div>
</template>

Saída:

TEXT
// Execução Bem-sucedida

8. Exemplo Completo: O Sistema de Rotas da MegaShop

VUE
<!-- pages/index.vue - Homepage -->
<template>
  <div>
    <section class="hero">
      <h1>MegaShop</h1>
      <p>Mais de 1 milhão de produtos, entregues mundialmente</p>
      <NuxtLink to="/products">Comprar Agora</NuxtLink>
    </section>
    <section class="featured">
      <ProductCard v-for="p in featured" :key="p.id" :product="p" />
    </section>
  </div>
</template>

<script setup lang="ts">
const { data: featured } = await useFetch('/api/products/featured')
</script>
VUE
<!-- pages/products/[id].vue - Detalhe do Produto -->
<template>
  <div v-if="product">
    <h1>{{ product.name }}</h1>
    <p class="price">${{ product.price }} USD</p>
    <button @click="addToCart">Adicionar ao Carrinho</button>
    <button @click="goBack">Voltar à Lista</button>
  </div>
  <div v-else>
    <p>Produto não encontrado</p>
    <NuxtLink to="/products">Navegar Produtos</NuxtLink>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
const router = useRouter()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)

function addToCart() {
  navigateTo('/cart')
}

function goBack() {
  router.back()
}
</script>

❓Perguntas Frequentes

P Os parâmetros de rotas dinâmicas são strings ou números?
R Parâmetros de URL são sempre strings. Se precisar de números, converta manualmente: Number(route.params.id), ou deixe o tipo de retorno da API determinar o valor ao usar useFetch.
P Qual é a diferença entre [id].vue e [...slug].vue?
R [id] corresponde apenas um único segmento de caminho (/products/123), enquanto [...slug] corresponde um caminho multi-segmento (/a/b/c), onde slug é um array. Rotas catch-all são adequadas para categorias com número ilimitado de níveis.
P A página pai para uma rota aninhada precisa existir obrigatoriamente?
R Sim, uma rota aninhada só é formada quando tanto a página pai products.vue quanto o subdiretório products/ existem. Se você deseja apenas a rota filha, não crie a página pai.
P Qual é a diferença entre NuxtLink e uma tag a comum?
R NuxtLink é usado para navegação no lado do cliente (sem atualizar a página), enquanto a tag a aciona uma atualização completa da página. Use NuxtLink para navegação interna e a tag a para links externos.
P Como configurar uma página 404 personalizada?
R Basta criar um arquivo pages/404.vue. O Nuxt 3 exibe automaticamente esta página quando nenhuma rota corresponde à requisição. Você também pode lidar com isso em uma rota catch-all.
P Qual é a relação entre routeRules e rotas?
R routeRules são configurados no nuxt.config.ts para especificar estratégias de renderização (SSR/ISR/CSR) com base em caminhos de rotas; elas não afetam as definições de rotas. Rotas são definidas pelos arquivos no diretório pages/; routeRules apenas controlam o comportamento de renderização.

📖Resumo


📝Exercícios

  1. Exercício Básico (Dificuldade: ⭐): Crie pages/about.vue e pages/contact.vue, e verifique se as rotas são geradas automaticamente.
  2. Problema Avançado (Dificuldade ⭐⭐): Implemente roteamento dinâmico de dois níveis /products/[category]/[id] e exiba os parâmetros "category" e "id" na página.
  3. Desafio (Dificuldade: ⭐⭐⭐): Implemente uma rota catch-all [...slug].vue que possa renderizar caminhos multi-nível como /docs/getting-started/installation e exiba uma barra de navegação breadcrumb.

---|

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%