7 промтов для Vue.js и Nuxt: компоненты, composables и роутинг — шпаргалка для разработчика

Введение

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}&current_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}&current_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 станет чище, а дедлайны — ближе.

← Все статьи

Комментарии

Читайте также

Интеграция Banana Pi с AI-агентом ASI Biont: автоматизация на одноплатнике без единой строки кода

14 июля 2026

Telegram Bot Development: как автоматизировать бизнес и заработать на ботах в 2026 году

14 июля 2026

AI-агент оживляет завод: интеграция Modbus RTU (RS-485) с ASI Biont для предиктивного обслуживания

14 июля 2026

Uber не хочет быть «всем для всех»: что на самом деле сказал продакт-директор про отели, роботакси и будущее платформы

14 июля 2026

Курс «Промышленный интернет вещей (IIoT) и системы SCADA»: ваш путь к Индустрии 4.0 в 2026 году

14 июля 2026

ИИ незаметно меняет мнения пользователей в соцсетях: как алгоритмы формируют нашу реальность

14 июля 2026

CKA + CKAD — Kubernetes Administrator & Developer: как подготовиться к сертификации в 2026 году с AI-тьютором

14 июля 2026

Как перестать терять сделки из-за языка: обзор курса «Английский для бизнеса» на asibiont.com

14 июля 2026

Трансформационное лидерство и стратегическое мышление CEO: Программа для основателей на уровне Гарварда, желающих овладеть принятием решений

14 июля 2026