Введение
Начинаете новый Vue.js проект, но backend еще не готов? Не хотите ждать неделями, пока API будет разработан? В этом туториале вы создадите полноценное Todo приложение на Vue.js 3 с API интеграцией за 15 минут — без единой строки backend кода.
✅ Что вы получите в конце:
- ✅ Рабочее Todo приложение с полным CRUD функционалом
- ✅ Vue.js 3 + TypeScript + Vite (современный стек)
- ✅ Composition API с composables
- ✅ Pinia для управления состоянием
- ✅ Интеграция с Mock API (реальные HTTP запросы)
- ✅ Обработка ошибок и loading states
- ✅ Deploy на Vercel (готово к продакшену)
- ✅ Полный исходный код на GitHub
💡 Для кого этот туториал:
- Начинающие Vue.js разработчики: Изучите работу с API
- Опытные разработчики: Ускорьте прототипирование
- Frontend команды: Не ждите backend, начните прямо сейчас
- Студенты: Создайте портфолио проект за 15 минут
📋 План действий (15 минут)
- Что мы создадим (1 мин)
- Шаг 1: Setup проекта (2 мин)
- Шаг 2: Создание Mock API (3 мин)
- Шаг 3: Настройка HTTP клиента (2 мин)
- Шаг 4: Vue Composables для API (3 мин)
- Шаг 5: Pinia Store интеграция (2 мин)
- Шаг 6: Создание компонентов (1 мин)
- Шаг 7: Deploy на Vercel (1 мин)
Что мы создадим 🎯
Мы создадим классическое Todo приложение с полноценным API. Это идеальный проект для изучения, так как он включает все основные операции:
| Функция | API Endpoint | Метод |
|---|---|---|
| Получить все задачи | GET /todos |
Read |
| Создать задачу | POST /todos |
Create |
| Обновить задачу | PUT /todos/:id |
Update |
| Удалить задачу | DELETE /todos/:id |
Delete |
Технологический стек
- Vue.js 3 — прогрессивный JavaScript фреймворк
- TypeScript — Типизация
- Vite — Сборщик (быстрее Webpack)
- Composition API — Современный подход Vue 3
- Pinia — State management (преемник Vuex)
- Axios — HTTP клиент
- LightBox API — Mock API платформа
Шаг 1: Setup проекта (2 минуты)
1 Создайте Vue.js приложение с Vite
# Создаем проект
npm create vite@latest todo-app -- --template vue-ts
# Переходим в директорию
cd todo-app
# Устанавливаем зависимости
npm install
# Устанавливаем дополнительные библиотеки
npm install axios pinia @vueuse/core
2 Структура проекта
todo-app/
├── src/
│ ├── api/
│ │ └── todos.ts # API функции
│ ├── composables/
│ │ └── useTodos.ts # Vue composable для todos
│ ├── stores/
│ │ └── todos.ts # Pinia store
│ ├── components/
│ │ ├── TodoList.vue # Список задач
│ │ ├── TodoItem.vue # Одна задача
│ │ └── AddTodo.vue # Форма добавления
│ ├── types/
│ │ └── todo.ts # TypeScript типы
│ ├── App.vue # Главный компонент
│ └── main.ts # Entry point
├── package.json
└── vite.config.ts
Шаг 2: Создание Mock API (3 минуты)
1 Зарегистрируйтесь на LightBox API
Перейдите на lightboxapi.ru и создайте бесплатный аккаунт.
2 Создайте workspace
В dashboard создайте новый workspace с именем todo-app.
3 Настройте endpoints
Endpoint 1: GET /todos
{
"todos": [
{
"id": "1",
"title": "Изучить Vue 3 Composition API",
"completed": false,
"createdAt": "2025-10-22T10:00:00Z"
},
{
"id": "2",
"title": "Интегрировать Mock API",
"completed": true,
"createdAt": "2025-10-22T09:00:00Z"
}
]
}
Endpoint 2: POST /todos
{
"id": "{randomUUID}",
"title": "{body.title}",
"completed": false,
"createdAt": "{$timestamp}"
}
Endpoint 3: PUT /todos/:id
{
"id": "{params.id}",
"title": "{body.title}",
"completed": "{body.completed}",
"createdAt": "{existing.createdAt}"
}
Endpoint 4: DELETE /todos/:id
{
"success": true,
"message": "Todo deleted"
}
Скопируйте URL вашего Mock API, например: https://lightboxapi.ru/your-workspace
Шаг 3: Настройка HTTP клиента (2 минуты)
1 Создайте TypeScript типы
Файл: src/types/todo.ts
export interface Todo {
id: string;
title: string;
completed: boolean;
createdAt: string;
}
export interface CreateTodoDto {
title: string;
}
export interface UpdateTodoDto {
title?: string;
completed?: boolean;
}
2 Настройте Axios клиент
Файл: src/api/todos.ts
import axios from 'axios';
import type { Todo, CreateTodoDto, UpdateTodoDto } from '../types/todo';
const API_BASE_URL = import.meta.env.VITE_API_URL || 'https://lightboxapi.ru/your-workspace';
const apiClient = axios.create({
baseURL: API_BASE_URL,
headers: {
'Content-Type': 'application/json',
},
});
export const todosApi = {
// Получить все задачи
async getAll(): Promise {
const response = await apiClient.get<{ todos: Todo[] }>('/todos');
return response.data.todos;
},
// Создать задачу
async create(data: CreateTodoDto): Promise {
const response = await apiClient.post('/todos', data);
return response.data;
},
// Обновить задачу
async update(id: string, data: UpdateTodoDto): Promise {
const response = await apiClient.put(`/todos/${id}`, data);
return response.data;
},
// Удалить задачу
async delete(id: string): Promise {
await apiClient.delete(`/todos/${id}`);
},
};
3 Настройте переменные окружения
Файл: .env
VITE_API_URL=https://lightboxapi.ru/your-workspace
Шаг 4: Vue Composables для API (3 минуты)
Vue 3 Composition API позволяет создавать переиспользуемые логические части — composables. Это современный подход для работы с API.
1 Создайте composable для todos
Файл: src/composables/useTodos.ts
import { ref, computed } from 'vue';
import { todosApi } from '../api/todos';
import type { Todo, CreateTodoDto, UpdateTodoDto } from '../types/todo';
export function useTodos() {
const todos = ref([]);
const loading = ref(false);
const error = ref(null);
// Вычисляемое свойство для количества задач
const todosCount = computed(() => todos.value.length);
const completedCount = computed(() =>
todos.value.filter(t => t.completed).length
);
// Загрузить все задачи
const fetchTodos = async () => {
loading.value = true;
error.value = null;
try {
todos.value = await todosApi.getAll();
} catch (err: any) {
error.value = err.message || 'Ошибка загрузки задач';
console.error('Error fetching todos:', err);
} finally {
loading.value = false;
}
};
// Создать задачу
const createTodo = async (data: CreateTodoDto) => {
loading.value = true;
error.value = null;
try {
const newTodo = await todosApi.create(data);
todos.value.push(newTodo);
return newTodo;
} catch (err: any) {
error.value = err.message || 'Ошибка создания задачи';
console.error('Error creating todo:', err);
throw err;
} finally {
loading.value = false;
}
};
// Обновить задачу
const updateTodo = async (id: string, data: UpdateTodoDto) => {
loading.value = true;
error.value = null;
try {
const updated = await todosApi.update(id, data);
const index = todos.value.findIndex(t => t.id === id);
if (index !== -1) {
todos.value[index] = updated;
}
return updated;
} catch (err: any) {
error.value = err.message || 'Ошибка обновления задачи';
console.error('Error updating todo:', err);
throw err;
} finally {
loading.value = false;
}
};
// Удалить задачу
const deleteTodo = async (id: string) => {
loading.value = true;
error.value = null;
try {
await todosApi.delete(id);
todos.value = todos.value.filter(t => t.id !== id);
} catch (err: any) {
error.value = err.message || 'Ошибка удаления задачи';
console.error('Error deleting todo:', err);
throw err;
} finally {
loading.value = false;
}
};
// Переключить статус задачи
const toggleTodo = async (id: string) => {
const todo = todos.value.find(t => t.id === id);
if (todo) {
await updateTodo(id, { completed: !todo.completed });
}
};
return {
todos,
loading,
error,
todosCount,
completedCount,
fetchTodos,
createTodo,
updateTodo,
deleteTodo,
toggleTodo,
};
}
Шаг 5: Pinia Store интеграция (2 минуты)
Pinia — это официальный state management для Vue 3. Он проще Vuex и имеет лучшую TypeScript поддержку. Мы можем использовать store вместо composable, если нужно разделить логику.
1 Настройте Pinia
Файл: src/main.ts
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
const app = createApp(App);
app.use(createPinia());
app.mount('#app');
2 Создайте Pinia store (опционально)
Файл: src/stores/todos.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { todosApi } from '../api/todos';
import type { Todo, CreateTodoDto, UpdateTodoDto } from '../types/todo';
export const useTodosStore = defineStore('todos', () => {
const todos = ref([]);
const loading = ref(false);
const error = ref(null);
const todosCount = computed(() => todos.value.length);
const completedCount = computed(() =>
todos.value.filter(t => t.completed).length
);
async function fetchTodos() {
loading.value = true;
error.value = null;
try {
todos.value = await todosApi.getAll();
} catch (err: any) {
error.value = err.message || 'Ошибка загрузки задач';
} finally {
loading.value = false;
}
}
async function createTodo(data: CreateTodoDto) {
loading.value = true;
try {
const newTodo = await todosApi.create(data);
todos.value.push(newTodo);
return newTodo;
} catch (err: any) {
error.value = err.message || 'Ошибка создания задачи';
throw err;
} finally {
loading.value = false;
}
}
async function updateTodo(id: string, data: UpdateTodoDto) {
const updated = await todosApi.update(id, data);
const index = todos.value.findIndex(t => t.id === id);
if (index !== -1) {
todos.value[index] = updated;
}
return updated;
}
async function deleteTodo(id: string) {
await todosApi.delete(id);
todos.value = todos.value.filter(t => t.id !== id);
}
async function toggleTodo(id: string) {
const todo = todos.value.find(t => t.id === id);
if (todo) {
await updateTodo(id, { completed: !todo.completed });
}
}
return {
todos,
loading,
error,
todosCount,
completedCount,
fetchTodos,
createTodo,
updateTodo,
deleteTodo,
toggleTodo,
};
});
Шаг 6: Создание компонентов (1 минута)
1 Главный компонент App.vue
<template>
<div class="app">
<h1>Vue.js Todo App</h1>
<AddTodo @todo-added="handleTodoAdded" />
<div v-if="loading">Загрузка...</div>
<div v-if="error" class="error">{ error }</div>
<TodoList
:todos="todos"
@toggle="handleToggle"
@delete="handleDelete"
/>
<div class="stats">
Всего: { todosCount }, Выполнено: { completedCount }
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue';
import { useTodos } from './composables/useTodos';
import TodoList from './components/TodoList.vue';
import AddTodo from './components/AddTodo.vue';
const {
todos,
loading,
error,
todosCount,
completedCount,
fetchTodos,
createTodo,
updateTodo,
deleteTodo,
toggleTodo,
} = useTodos();
onMounted(() => {
fetchTodos();
});
const handleTodoAdded = async (title: string) => {
await createTodo({ title });
};
const handleToggle = async (id: string) => {
await toggleTodo(id);
};
const handleDelete = async (id: string) => {
await deleteTodo(id);
};
</script>
<style scoped>
.app {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.error {
color: #ef4444;
padding: 12px;
background: #fee;
border-radius: 8px;
margin: 16px 0;
}
.stats {
margin-top: 20px;
padding: 12px;
background: #f3f4f6;
border-radius: 8px;
}
</style>
2 Компонент TodoList.vue
<template>
<ul class="todo-list">
<TodoItem
v-for="todo in todos"
:key="todo.id"
:todo="todo"
@toggle="$emit('toggle', todo.id)"
@delete="$emit('delete', todo.id)"
/>
</ul>
</template>
<script setup lang="ts">
import TodoItem from './TodoItem.vue';
import type { Todo } from '../types/todo';
defineProps<{ todos: Todo[] }>();
defineEmits<{
toggle: [id: string];
delete: [id: string];
}>();
</script>
3 Компонент AddTodo.vue
<template>
<form @submit.prevent="handleSubmit" class="add-todo">
<input
v-model="title"
type="text"
placeholder="Добавить задачу..."
required
/>
<button type="submit">Добавить</button>
</form>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const title = ref('');
const emit = defineEmits<{
todoAdded: [title: string];
}>();
const handleSubmit = () => {
if (title.value.trim()) {
emit('todoAdded', title.value);
title.value = '';
}
};
</script>
Шаг 7: Deploy на Vercel (1 минута)
1 Подготовьте проект к деплою
# Соберите проект
npm run build
# Проверьте, что dist/ папка создана
ls dist/
2 Deploy на Vercel
- Установите Vercel CLI:
npm i -g vercel - Выполните:
vercel - Следуйте инструкциям
- Добавьте переменную окружения
VITE_API_URLв настройках проекта
Или используйте GitHub интеграцию Vercel для автоматического деплоя.
Результат 🎉
Поздравляем! Вы создали полноценное Vue.js приложение с API интеграцией за 15 минут. Приложение работает с реальными HTTP запросами к Mock API и готово к работе.
Что мы изучили:
- ✅ Vue.js 3 Composition API и composables
- ✅ TypeScript типизация для Vue
- ✅ Работа с HTTP запросами через Axios
- ✅ Pinia для state management
- ✅ Структура Vue компонентов
- ✅ Интеграция с Mock API
- ✅ Deploy на Vercel
Следующие шаги 🚀
- Добавьте роутинг: Установите Vue Router для навигации
- Улучшите UI: Добавьте стили и анимации
- Добавьте валидацию: Используйте VeeValidate или Yup
- Интегрируйте реальный API: Замените Mock API URL на production
- Добавьте тесты: Используйте Vitest для unit тестов
Создайте Mock API за 2 минуты
Не ждите backend — начните разработку Vue.js приложения прямо сейчас с LightBox API. Бесплатный старт для всех разработчиков.
Попробовать бесплатно →