10 Projetos Práticos para Aprender Vue.js do Zero

10 Projetos Práticos para Aprender Vue.js do Zero





Projetos práticos para aprender Vue.js



Projeto 1 — To-do com Vue 3 (Composition API)

Um task tracker simples que utiliza reatividade, computed e o script setup para demonstrar fluxo básico de criação, marcação concluída e contagem de itens restantes.

Conceitos principais

  • Reatividade com ref: acompanhar mudanças de listas e estados de tarefas.
  • Computed para lógica derivada (tarefas restantes).
  • Funções de manipulação (add, toggle) mantendo o estado imutável na prática.

Código mínimo

<script setup>
import { ref, computed } from 'vue';

const tasks = ref([
  { id: 1, text: 'Configurar projeto', done: false },
  { id: 2, text: 'Criar componentes básicos', done: false }
]);

const newTask = ref('');

const add = () => {
  const t = newTask.value.trim();
  if (!t) return;
  tasks.value.push({ id: Date.now(), text: t, done: false });
  newTask.value = '';
};

const toggle = (id) => {
  const item = tasks.value.find(t => t.id === id);
  if (item) item.done = !item.done;
};

const remaining = computed(() => tasks.value.filter(t => !t.done).length);
</script>

Observação: este pode ser o seu esqueleto para projetos futuros. Expanda com filtros, persistência local e testes unitários para evoluir o fluxo.

Projeto 2 — Card reutilizável com props e slots

Crie componentes reutilizáveis com slots para conteúdo, props para dados e estilos consistentes, aumentando a manutenibilidade do código.

InfoCard (Card.vue, conceito)

<template>
  <div class="info-card">
    <h4>{{ title }}</h4>
    <div>
      <slot name="content"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: 'InfoCard',
  props: {
    title: String
  }
}
</script>

Exemplo de uso

<template>
  <InfoCard title="Itens do dia">
    <template v-slot:content>
      <ul>
        <li>Revisar pull requests</li>
        <li>Atualizar dependências</li>
      </ul>
    </template>
  </InfoCard>
</template>
<script>
import InfoCard from './InfoCard.vue';
export default { components: { InfoCard } }
</script>

Prática recomendada: crie um conjunto de cartões com data-bindings dinâmicos e slots para conteúdos variados. Utilize props para título, subtítulo e cor de tema para cada cartão.

Projeto 3 — Consumindo APIs com fetch e onMounted

Exposição de chamadas assíncronas com manejo de loading e erro, ilustrando como popular dados de uma API pública e exibir estados no template.

Código de exemplo

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

const users = ref([]);
const loading = ref(false);
const error = ref(null);

onMounted(async () => {
  loading.value = true;
  try {
    const res = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!res.ok) throw new Error('Erro ao carregar dados');
    users.value = await res.json();
  } catch (e) {
    error.value = e.message;
  } finally {
    loading.value = false;
  }
});
</script>

O que observar

  • Tratamento de estados: carregando, sucesso, erro.
  • Renderização condicional com v-if/v-else.
  • Uso de v-for para iterar resultados de API.

Boas práticas: isolar a lógica de fetch em composables para reutilizar em outros componentes e facilitar testes.

Projeto 4 — Dashboard simples com Pinia

Introdução ao Pinia para gerenciar estado compartilhado entre componentes, com getter para métricas e ações para mutação de dados.

Store (useTaskStore)

// store/task.js
import { defineStore } from 'pinia';

export const useTaskStore = defineStore('task', {
  state: () => ({
    items: []
  }),
  actions: {
    add(text) {
      this.items.push({ id: Date.now(), text, done: false });
    },
    toggle(id) {
      const item = this.items.find(i => i.id === id);
      if (item) item.done = !item.done;
    }
  },
  getters: {
    remaining: (state) => state.items.filter(i => !i.done).length
  }
});

Uso no componente

// Em componente Vue
import { useTaskStore } from '@/stores/task';
const store = useTaskStore();
store.add('Nova tarefa via Pinia');
console.log(store.remaining);

Observação prática: conecte o Pinia ao Vue na inicialização da aplicação (app.use(createPinia())). O padrão facilita escalabilidade do estado conforme o projeto cresce.