Estrutura Organizacional de Projetos Vue 3
O ecossistema Vue 3, aliado à ferramenta de construção Vite, estabeleceu um padrão moderno para o desenvolvimento front-end. Esta combinação oferece configurações otimizadas por padrão e uma organização de pastas que facilita a ecsalabilidade. Abaixo, detalhamos a estrutura recomendada para projetos de nível profissional.
projeto-vue/
├── node_modules/ # Dependências instaladas via npm
├── public/ # Recursos estáticos brutos (sem build processamento)
│ └── favicon.ico # Ícone da aba do navegador
├── src/ # Diretori core da lógica
│ ├── api/ # Camada de integração com backend
│ │ └── auth.js # Configuração Axios e endpoints de autenticação
│ ├── assets/ # Recursos importados via JS
│ │ ├── styles/ # Arquivos CSS globais e scoped
│ │ ├── imgs/ # Imagens processadas pelo Webpack/Vite
│ │ └── fonts/ # Fontes customizadas
│ ├── components/ # Componentes reutilizáveis
│ │ ├── base/ # Elementos básicos (Button, Input)
│ │ └── layout/ # Estruturas macro (Header, Sidebar)
│ ├── composables/ # Lógica encapsulada (Hooks do Vue 3)
│ │ └── useAuth.js # Hooks para gerenciamento de login
│ ├── router/ # Definição de rotas (vue-router 4+)
│ │ └── index.js # Mapa de rotas e guarda de navegação
│ ├── stores/ # Gerenciamento de estado global (Pinia)
│ │ └── cart.store.js # Módulo específico de carrinho
│ ├── views/ # Páginas completas associadas às rotas
│ │ ├── Dashboard/ # Página principal
│ │ │ └── index.vue
│ ├── App.vue # Raiz da aplicação
│ ├── main.js # Ponto de entrada e boot do framework
│ └── main.css # Variáveis globais e reset
├── .env.local # Variáveis de ambiente (não versionar secrets)
├── vite.config.js # Configurações de servidor e bundling
└── package.json # Metadados e scripts de execução
Análise dos Principais Módulos
- src/api: Centraliza todas as requisições HTTP. Recomenda-se criar interceptores para tratamento automático de tokens JWT e erros de conexão.
- src/composables: Diferente de componentes, estes arquivos são lógicas puras que podem ser importadas em múltiplas visões. O prefixo
useé obrigatório por convenção. - src/stores: No Vue 3, o Pinia substitui o Vuex. Cada módulo deve refletir um domínio de negócio distinto (ex: usuário, produtos, preferências).
- vite.config.js: Permite redirecionamentos de API (proxy) para resolver problemas de CORS durante o desenvolvimento local.
Mecanismos de Transferência de Dados entre Componentes
A comunicação no Vue ocorre principalmente através de props (descendente) e eventos (ascendente). Para cenários mais complexos, utilizam-se soluções como estado global ou injeção direta.
1. Passagem de Dados (Pai → Filho)
A técnica mais fundamental utiliza a declaração de props. O componente filho recebe dados apenas como leitura, garantindo fluxo unidirecional.
<template>
<div class="card">
<h2>{{ titulo }}</h2>
<p>Status Admin: {{ isAdmin ? 'Sim' : 'Não' }}</p>
<ul>
<li v-for="item in itens" :key="item.id">{{ item.nome }}</li>
</ul>
</div>
</template>
<script setup>
// Definição de contratos de entrada
const props = defineProps({
titulo: { type: String, required: true },
itens: {
type: Array,
default: () => [] // Obrigatório usar função para arrays
},
isAdmin: Boolean
})
</script>
Nota-se que a modificação direta de arrays em props é desencorajada pois afeta o pai. Alterações devem sempre notificar o componente ascendente.
2. Notificação para o Acima ($emit)
Quando o componente descendente necessita disparar uma ação ou enviar informação de volta, usa-se o emit.
<template>
<button @click="salvarRegistro">Salvar Dados</button>
</template>
<script setup>
const emit = defineEmits(['registrar-mudanca'])
const salvarRegistro = () => {
const payload = { id: Date.now(), valor: 'novo dado' }
emit('registrar-mudanca', payload)
}
</script>
No componente pai, o evento escuta via atributo de evento (ex: @registrar-mudanca="funcao"). Isso mantém o desacoplamento entre visão e lógica.
3. Bind Unidirecional Duplo (v-model)
Sintaxe abstrata que combina prop e evento para vincular valores em tempo real.
<!-- Parental -->
<CampoInput v-model="dadosForm" />
<script setup>
import { ref } from 'vue'
const dadosForm = ref('')
</script>
<!-- Filial -->
<template>
<input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</template>
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
Para múltiplos bindings, pode-se personalizar o nome da chave usando v-model:campo="variavel" na sintaxe Vue 3.
4. Estado Global (Pinia)
A biblioteca oficial para gerenciar estado complexo elimina a necessidade de passar props por dezenas de níveis hierárquicos.
// Criação do Store
import { defineStore } from 'pinia'
export const useDadosApp = defineStore('app', {
state: () => ({
acessoToken: null,
listaTarefas: []
}),
getters: {
possuiAcesso: (state) => !!state.acessoToken
},
actions: {
fazerLogin(token) {
this.acessoToken = token
}
}
})
// Uso no Componente
import { useDadosApp } from '@/stores/main'
const store = useDadosApp()
const login = () => {
store.fazerLogin('token_123')
}
</script>
5. Injeção de Dependência (Provide / Inject)
Útil para evitar prop drilling em árvores muito profundas. O componente ancestral fornece e os descendentes consomem.
<!-- Ancestral -->
<script setup>
import { provide, ref } from 'vue'
const corTema = ref('claro')
provide('tema', corTema)
</script>
<