Vue Application Structure Overview
Build well-organized Vue 3 applications using Composition API, proper file organization, and TypeScript for type safety and maintainability.
When to Use Large-scale Vue applications Component library development Reusable composable hooks Complex state management Performance optimization Implementation Examples 1. Vue 3 Composition API Component // useCounter.ts (Composable) import { ref, computed } from 'vue';
export function useCounter(initialValue = 0) { const count = ref(initialValue);
const doubled = computed(() => count.value * 2); const increment = () => count.value++; const decrement = () => count.value--; const reset = () => count.value = initialValue;
return { count, doubled, increment, decrement, reset }; }
// Counter.vue
Count: {{ count }} Doubled: {{ doubled }}
- Async Data Fetching Composable // useFetch.ts import { ref, computed, onMounted } from 'vue';
interface UseFetchOptions { immediate?: boolean; }
export function useFetch
const isLoading = computed(() => loading.value); const hasError = computed(() => error.value !== null);
const fetch = async () => { loading.value = true; error.value = null;
try {
const response = await globalThis.fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
data.value = await response.json();
} catch (e) {
error.value = e instanceof Error ? e : new Error(String(e));
} finally {
loading.value = false;
}
};
const refetch = () => fetch();
if (options.immediate !== false) { onMounted(fetch); }
return { data, loading: isLoading, error: hasError, fetch, refetch }; }
// UserList.vue
Loading... Error loading users
-
Component Organization Structure src/ ├── components/ │ ├── common/ │ │ ├── Button.vue │ │ ├── Card.vue │ │ └── Modal.vue │ ├── forms/ │ │ ├── FormInput.vue │ │ └── FormSelect.vue │ └── layouts/ │ ├── Header.vue │ └── Sidebar.vue ├── composables/ │ ├── useCounter.ts │ ├── useFetch.ts │ └── useForm.ts ├── services/ │ ├── api.ts │ └── auth.ts ├── stores/ │ ├── user.ts │ └── auth.ts ├── types/ │ ├── models.ts │ └── api.ts ├── App.vue └── main.ts
-
Form Handling Composable // useForm.ts import { ref, reactive } from 'vue';
interface UseFormOptions
export function useForm
const handleSubmit = async (e?: Event) => { e?.preventDefault(); isSubmitting.value = true;
try {
await options.onSubmit(formData);
} catch (error) {
const err = error as any;
if (err.fieldErrors) {
Object.assign(errors, err.fieldErrors);
}
} finally {
isSubmitting.value = false;
}
};
const reset = () => { Object.assign(formData, options.initialValues); Object.keys(errors).forEach(key => delete errors[key]); };
return { formData, errors, isSubmitting, handleSubmit, reset }; }
// LoginForm.vue
- Pinia Store (State Management) // stores/user.ts import { defineStore } from 'pinia'; import { ref, computed } from 'vue';
interface User { id: number; name: string; email: string; }
export const useUserStore = defineStore('user', () => {
const user = ref
const isLoggedIn = computed(() => user.value !== null);
const fetchUser = async (id: number) => {
isLoading.value = true;
try {
const response = await fetch(/api/users/${id});
user.value = await response.json();
} finally {
isLoading.value = false;
}
};
const logout = () => { user.value = null; };
return { user, isLoading, isLoggedIn, fetchUser, logout }; });
// Usage in component import { useUserStore } from '@/stores/user';
export default { setup() { const userStore = useUserStore(); userStore.fetchUser(1); return { userStore }; } };
Best Practices Organize by features or domains Use Composition API for logic reuse Extract composables for shared logic Use TypeScript for type safety Implement proper error handling Keep components focused and testable Use Pinia for state management Resources Vue 3 Documentation Vue Composition API Pinia State Management