Введение
Vue.js и его мета-фреймворк Nuxt — одни из самых популярных инструментов для создания современных веб-приложений. Согласно опросу State of JS 2025, Vue.js сохраняет позиции в тройке лидеров по удовлетворённости разработчиков, а Nuxt уверенно растёт благодаря упрощению SSR, гибридной генерации и модульной архитектуре. Однако даже опытные разработчики тратят до 30% времени на рутинные задачи: написание шаблонов компонентов, настройку composables и конфигурацию роутинга. Использование ИИ-ассистентов (ChatGPT, Claude, Gemini) с правильно составленными промтами сокращает эту работу в 3–5 раз. В этой статье — 7 готовых промтов, которые покрывают 80% повседневных задач: от создания UI-компонентов до Pinia store. Каждый промт сопровождается примером использования и пояснением, когда его применять.
1. Промт для создания компонента с props, slots и emits
Когда использовать: Вы начинаете новый проект или добавляете переиспользуемый UI-компонент (кнопку, карточку, модальное окно).
Промт:
Напиши Vue 3 компонент <ComponentName> с Composition API (script setup).
Требования:
- Принимает props: title (string, required), variant (enum: 'primary' | 'secondary', default 'primary'), disabled (boolean, default false).
- Имеет слот default для контента и слот footer для действий.
- Эмитит события: click, close.
- Стили scoped, используй CSS-переменные для темизации.
- Следуй принципу единой ответственности — компонент не должен знать о бизнес-логике.
Пример результата:
<script setup lang="ts">
interface Props {
title: string
variant?: 'primary' | 'secondary'
disabled?: boolean
}
const props = withDefaults(defineProps<Props>(), {
variant: 'primary',
disabled: false
})
const emit = defineEmits<{
(e: 'click', payload: MouseEvent): void
(e: 'close'): void
}>()
const handleClick = (event: MouseEvent) => {
if (!props.disabled) emit('click', event)
}
</script>
<template>
<div
class="custom-component"
:class="[`custom-component--${variant}`, { 'custom-component--disabled': disabled }]"
>
<header class="custom-component__header">
<h3>{{ title }}</h3>
<button class="custom-component__close" @click="emit('close')">×</button>
</header>
<slot />
<footer v-if="$slots.footer" class="custom-component__footer">
<slot name="footer" />
</footer>
</div>
</template>
<style scoped>
.custom-component {
border: 1px solid var(--color-border);
border-radius: 8px;
padding: 16px;
background: var(--color-bg-primary);
transition: opacity 0.2s;
}
.custom-component--disabled {
opacity: 0.5;
pointer-events: none;
}
.custom-component__header {
display: flex;
justify-content: space-between;
align-items: center;
}
.custom-component__close {
background: none;
border: none;
cursor: pointer;
font-size: 1.5rem;
}
</style>
2. Промт для создания composable с реактивным состоянием и методами
Когда использовать: Нужно вынести логику (работа с API, управление формой, таймеры) в переиспользуемую функцию.
Промт:
Создай composable useAsyncData для Vue 3.
Требования:
- Принимает URL (string) и опциональные параметры запроса.
- Возвращает: data (ref), error (ref), isLoading (ref), execute() — метод для повторного запроса.
- Используй fetch с AbortController для отмены запроса при размонтировании компонента.
- Обработай ошибки сети и некорректные HTTP-статусы.
- Типизируй возвращаемые данные с помощью Generics.
Пример использования в компоненте:
<script setup lang="ts">
import { useAsyncData } from '@/composables/useAsyncData'
const { data, error, isLoading, execute } = useAsyncData<{ id: number; name: string }>('/api/users')
</script>
<template>
<div>
<p v-if="isLoading">Загрузка...</p>
<p v-else-if="error">Ошибка: {{ error.message }}</p>
<pre v-else>{{ data }}</pre>
<button @click="execute">Обновить</button>
</div>
</template>
3. Промт для динамической маршрутизации в Nuxt 3
Когда использовать: Настраиваете роутинг с параметрами, вложенными маршрутами или middleware.
Промт:
Создай структуру страниц Nuxt 3 для интернет-магазина:
- /products — список товаров (page)
- /products/[id] — детальная страница товара, получает id через useRoute()
- /products/[id]/edit — страница редактирования, защищённая middleware auth
- /cart — корзина с проверкой авторизации
- middleware auth должен перенаправлять на /login, если нет токена в cookie
- Используй definePageMeta для title и middleware
Пример реализации файла middleware/auth.ts:
export default defineNuxtRouteMiddleware((to, from) => {
const token = useCookie('auth_token')
if (!token.value) {
return navigateTo('/login')
}
})
Пример pages/products/[id].vue:
<script setup lang="ts">
definePageMeta({
title: 'Товар',
middleware: 'auth'
})
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
</script>
<template>
<div>
<h1>{{ product.title }}</h1>
<p>{{ product.description }}</p>
</div>
</template>
4. Промт для настройки Pinia store с actions и getters
Когда использовать: Нужно централизованное управление состоянием (корзина, пользователь, настройки).
Промт:
Напиши Pinia store для корзины покупок (defineStore).
Требования:
- State: items (массив {id, name, price, quantity}), totalQuantity (computed), totalPrice (computed).
- Actions: addItem(item), removeItem(id), clearCart(), updateQuantity(id, quantity).
- При изменении корзины сохраняй её в localStorage через watch.
- При инициализации загружай данные из localStorage.
- Типизируй state и actions с помощью TypeScript.
Пример реализации:
import { defineStore } from 'pinia'
import { ref, computed, watch } from 'vue'
interface CartItem {
id: number
name: string
price: number
quantity: number
}
export const useCartStore = defineStore('cart', () => {
const items = ref<CartItem[]>([])
// Загрузка из localStorage
const saved = localStorage.getItem('cart')
if (saved) items.value = JSON.parse(saved)
const totalQuantity = computed(() => items.value.reduce((sum, item) => sum + item.quantity, 0))
const totalPrice = computed(() => items.value.reduce((sum, item) => sum + item.price * item.quantity, 0))
function addItem(newItem: Omit<CartItem, 'quantity'>) {
const existing = items.value.find(item => item.id === newItem.id)
if (existing) {
existing.quantity++
} else {
items.value.push({ ...newItem, quantity: 1 })
}
}
function removeItem(id: number) {
items.value = items.value.filter(item => item.id !== id)
}
function clearCart() {
items.value = []
}
function updateQuantity(id: number, quantity: number) {
const item = items.value.find(item => item.id === id)
if (item) item.quantity = Math.max(1, quantity)
}
// Автосохранение
watch(items, (newVal) => {
localStorage.setItem('cart', JSON.stringify(newVal))
}, { deep: true })
return { items, totalQuantity, totalPrice, addItem, removeItem, clearCart, updateQuantity }
})
5. Промт для кастомной директивы (v-focus, v-tooltip)
Когда использовать: Нужна многократно используемая DOM-манипуляция, которая не вписывается в компонент.
Промт:
Создай кастомную директиву v-tooltip для Vue 3.
Требования:
- При наведении на элемент показывает тултип с текстом из атрибута v-tooltip.
- Позиционирование: top, bottom, left, right (передаётся как модификатор, по умолчанию top).
- Тултип должен быть элементом <div>, добавленным в body, стилизован с помощью CSS.
- При уходе мыши тултип удаляется из DOM.
- Типизируй директиву (DirectiveBinding).
Пример результата:
import { Directive } from 'vue'
const tooltipDirective: Directive<HTMLElement, string> = {
mounted(el, binding) {
let tooltip: HTMLDivElement | null = null
const showTooltip = () => {
tooltip = document.createElement('div')
tooltip.textContent = binding.value
tooltip.className = 'tooltip'
const position = binding.modifiers.bottom ? 'bottom' : binding.modifiers.left ? 'left' : binding.modifiers.right ? 'right' : 'top'
tooltip.classList.add(`tooltip--${position}`)
const rect = el.getBoundingClientRect()
tooltip.style.left = `${rect.left + window.scrollX}px`
tooltip.style.top = `${rect.top + window.scrollY - 30}px`
document.body.appendChild(tooltip)
}
const hideTooltip = () => {
if (tooltip) {
document.body.removeChild(tooltip)
tooltip = null
}
}
el.addEventListener('mouseenter', showTooltip)
el.addEventListener('mouseleave', hideTooltip)
}
}
export default tooltipDirective
6. Промт для оптимизации производительности с v-memo и keep-alive
Когда использовать: В списках с тысячами элементов или при частой перерисовке.
Промт:
Объясни и покажи примеры использования v-memo и <KeepAlive> в Vue 3 для оптимизации рендеринга.
Требования:
- Пример v-memo: список товаров, который перерисовывается только при изменении цены или названия.
- Пример <KeepAlive>: вкладки (tabs), содержимое которых не должно пересоздаваться при переключении.
- Добавь комментарии, объясняющие, почему эти оптимизации работают.
- Предупреди о случаях, когда v-memo может навредить (например, при использовании слотов).
Пример с KeepAlive:
<template>
<div>
<button v-for="tab in tabs" :key="tab.id" @click="activeTab = tab.id">{{ tab.name }}</button>
<KeepAlive>
<component :is="currentComponent" />
</KeepAlive>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import TabProfile from './TabProfile.vue'
import TabSettings from './TabSettings.vue'
const activeTab = ref('profile')
const currentComponent = computed(() => activeTab.value === 'profile' ? TabProfile : TabSettings)
</script>
7. Промт для интеграции внешнего API с useFetch и обработкой ошибок
Когда использовать: Подключаете сторонний сервис (например, погода, платежи, соцсети).
Промт:
Напиши composable useWeatherAPI для получения данных о погоде.
Требования:
- Используй useFetch из Nuxt 3 (или fetch в чистом Vue).
- URL: https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t_weather=true
- Принимает координаты (lat, lon).
- Возвращает: temperature, windspeed, weathercode (с расшифровкой).
- Обработай ошибки: сеть, таймаут (10 сек), некорректные координаты.
- Добавь retry-логику — 2 повтора с задержкой 1 секунда.
Пример использования:
export const useWeatherAPI = (lat: number, lon: number) => {
const url = computed(() => `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true`)
const { data, error, refresh, status } = useFetch(url, {
retry: 2,
retryDelay: 1000,
timeout: 10000,
onResponseError({ response }) {
console.error('Weather API error:', response.status)
}
})
const temperature = computed(() => data.value?.current_weather?.temperature ?? null)
const windspeed = computed(() => data.value?.current_weather?.windspeed ?? null)
return { temperature, windspeed, error, refresh, isLoading: status === 'pending' }
}
Заключение
Эти 7 промтов — не волшебная палочка, а рабочие инструменты, которые экономят часы ручного кодинга. Главное — адаптировать их под свой проект: заменить имена, типы и URL. Практика показывает, что после 3–4 использований вы начнёте писать свои промты на лету, комбинируя условия. Помните: ИИ отлично генерирует скелет, но бизнес-логику и тесты пишет разработчик. Держите эту шпаргалку под рукой — и ваш код на Vue.js и Nuxt станет чище, а дедлайны — ближе.
Комментарии