Search buenodc

Nesta página
  1. 1. MPA vs SPA — o que muda na navegação
  2. 2. Instalando e configurando o Vue Router
  3. 3. <RouterView> e <RouterLink>
  4. 4. Views — organizando as telas
  5. 5. Navegação programática — useRouter()
  6. 6. Parâmetros de rota — useRoute()
  7. 7. Fetch com DELETE
  8. Referência rápida

Vue Router — Roteamento Client-Side

Quando você usa o Gmail, clica em “Enviados” e a lista muda sem a página piscar. Quando você navega pelo Spotify, a música continua tocando enquanto você vai para outra tela. Nos dois casos, o navegador não está recarregando a página — o JavaScript está trocando o conteúdo exibido sem sair do mesmo HTML. Isso é roteamento client-side: a URL muda, o conteúdo muda, mas a aplicação permanece viva na memória.

O Vue Router é a biblioteca oficial para fazer isso em aplicações Vue 3. Ele mapeia URLs a componentes e gerencia a navegação sem recarregamento.


1. MPA vs SPA — o que muda na navegação

Numa aplicação tradicional (MPA — Multi Page Application), cada URL é um arquivo HTML diferente no servidor. Clicar num link faz o navegador carregar uma página nova do zero — perde-se o estado em memória, a música para, o carrinho some.

Numa SPA com Vue Router, existe apenas um arquivo HTML. O router intercepta a navegação, atualiza a URL no navegador e troca o componente renderizado — sem sair da aplicação.

O problema concreto:

<!-- ❌ link tradicional — recarrega a página, destrói o estado Vue -->
<a href="/sobre">Sobre</a>

<!-- ✅ RouterLink — navega sem reload, mantém a aplicação viva -->
<RouterLink to="/sobre">Sobre</RouterLink>

Usar <a href> numa SPA é como ligar o carro, ir até o destino e apagar o motor — na próxima vez, você precisa religar tudo do zero.


2. Instalando e configurando o Vue Router

Instalação

npm install vue-router

Criando o arquivo de rotas

Por convenção, as rotas ficam em src/router/index.js.

// src/router/index.js
import { createRouter, createWebHistory } from "vue-router";
import HomeView from "../views/HomeView.vue";
import PlaylistView from "../views/PlaylistView.vue";

const routes = [
  { path: "/", component: HomeView },
  { path: "/playlists/nova", component: PlaylistView },
];

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

export default router;
  • createRouter cria a instância do router
  • createWebHistory usa a History API do navegador — URLs limpas, sem #
  • routes é um array que mapeia cada URL a um componente

Registrando no main.js

// src/main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

const app = createApp(App);
app.use(router); // registra o plugin
app.mount("#app");

app.use(router) precisa vir antes de app.mount. Sem isso, <RouterView> e <RouterLink> não existem nos templates.


Com o router configurado, o App.vue deixa de conter o conteúdo da aplicação diretamente. Ele passa a ser a “casca” — com navegação e o espaço onde cada view é renderizada.

<!-- App.vue -->
<template>
  <nav>
    <RouterLink to="/">Início</RouterLink>
    <RouterLink to="/playlists/nova">Nova Playlist</RouterLink>
  </nav>

  <RouterView />
</template>
  • <RouterView /> é o “buraco” onde o componente da rota ativa é renderizado
  • <RouterLink to="..."> gera um <a> que navega sem recarregar a página

O Vue Router adiciona automaticamente a classe router-link-active no link da rota atual — útil para estilizar o item ativo na nav.


4. Views — organizando as telas

Por convenção, os componentes que representam telas completas ficam em src/views/. São componentes Vue normais — a diferença é só organizacional.

Cada view é responsável por buscar seus próprios dados. Não faz sentido buscar tudo no App.vue e passar para baixo via props — isso quebra o encapsulamento e faz o App.vue saber de tudo.

<!-- src/views/HomeView.vue -->
<template>
  <ul>
    <li v-for="musica in musicas" :key="musica.id">{{ musica.titulo }}</li>
  </ul>
</template>

<script setup>
import { ref, onMounted } from "vue";

const musicas = ref([]);

onMounted(async () => {
  const res = await fetch("https://api.exemplo.com/musicas");
  musicas.value = await res.json(); // cada view cuida dos próprios dados
});
</script>

Quando o usuário navega para /, o Vue monta HomeView e dispara o onMounted — os dados são buscados nesse momento, não antes.


5. Navegação programática — useRouter()

Às vezes precisamos navegar por código — após salvar um formulário, por exemplo. Para isso, usamos useRouter().

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

const router = useRouter();

async function salvar(produto) {
  await fetch("https://api.exemplo.com/products", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(produto),
  });

  router.push("/"); // redireciona para a home após salvar
}
</script>
  • useRouter() retorna a instância do router
  • router.push('/destino') navega para a rota indicada — equivale ao usuário clicar num <RouterLink>

Sem o router.push, o usuário ficaria na tela do formulário depois de salvar, sem feedback visual de que a operação foi concluída.


6. Parâmetros de rota — useRoute()

Quando precisamos de uma rota dinâmica — como a página de detalhe de um item — usamos :id na definição da rota.

// src/router/index.js
{ path: "/products/:id", component: ProdutoDetalheView }

Para ler o valor do parâmetro na view, usamos useRoute():

<script setup>
import { ref, onMounted } from "vue";
import { useRoute } from "vue-router";

const route = useRoute();
const produto = ref(null);

onMounted(async () => {
  const id = route.params.id; // lê o :id da URL atual
  const res = await fetch(`https://api.exemplo.com/products/${id}`);
  produto.value = await res.json();
});
</script>

useRoute() dá acesso à rota atual. useRouter() dá acesso ao router para navegar. São funções diferentes.


7. Fetch com DELETE

O método DELETE remove um recurso no servidor. Não precisa de body — o id vai na URL.

async function remover(id) {
  const res = await fetch(`https://api.exemplo.com/products/${id}`, {
    method: "DELETE",
  });

  if (!res.ok) throw new Error("Erro ao remover");

  // após confirmar o DELETE no servidor, atualizar o estado local
  itens.value = itens.value.filter((item) => item.id !== id);
}

Por que usar .filter() em vez de fazer um novo GET após o DELETE?

  • O servidor confirmou a remoção — não precisamos perguntar de novo o que ele tem
  • Um GET extra é uma requisição desnecessária que aumenta latência
  • .filter() cria um novo array sem o item removido e o Vue atualiza a tela imediatamente

filter não modifica o array original — retorna um novo array. Por isso atribuímos o resultado de volta a itens.value.


Referência rápida

RecursoPara que serve
npm install vue-routerInstalar a biblioteca
createRouter({ history, routes })Criar a instância do router
createWebHistory()URLs limpas sem #
app.use(router)Registrar o router na aplicação
<RouterView />Onde a view da rota atual é renderizada
<RouterLink to="...">Navegar sem recarregar a página
useRouter()Acessar o router para navegar por código
router.push('/rota')Navegar programaticamente
useRoute()Acessar dados da rota atual (params, query)
route.params.idLer parâmetro dinâmico da URL
fetch(url, { method: 'DELETE' })Remover recurso no servidor
.filter()Remover item do array local após DELETE