Composables и утилиты
Composable — функция, которая прячет повторяющуюся логику с реактивными данными, например счётчик лайков. Её имя принято начинать с use. Во Vue такие функции импортируют вручную, а Nuxt подключает их автоматически из папки app/composables/. Для обычных функций без реактивности есть соседняя папка app/utils/.
Свой composable
npx nuxi add composable useLikesКоманда создаст app/composables/useLikes.ts. Замените содержимое:
// app/composables/useLikes.ts
export function useLikes() {
const likes = ref(0)
function like() {
likes.value++
}
return { likes, like }
}ref тоже не импортирован: функции Vue (ref, computed, watch, onMounted и другие) Nuxt подключает сам.
Использование
Добавьте кнопку лайка в карточку app/components/PostCard.vue:
<!-- app/components/PostCard.vue -->
<script setup lang="ts">
defineProps<{
post: { id: number; title: string; text: string }
}>()
const { likes, like } = useLikes()
</script>
<template>
<article class="post-card">
<h3>
<NuxtLink :to="`/posts/${post.id}`">{{ post.title }}</NuxtLink>
</h3>
<button @click="like">Нравится: {{ likes }}</button>
</article>
</template>У каждой карточки на странице /posts свой счётчик: функция вызывается заново для каждого компонента и создаёт новый ref.
Утилиты
Функции без реактивности кладут в app/utils/. Создайте файл app/utils/formatDate.ts:
// app/utils/formatDate.ts
export function formatDate(date: string) {
return new Date(date).toLocaleDateString('ru-RU', {
day: 'numeric',
month: 'long',
year: 'numeric'
})
}Теперь в любом компоненте можно написать {{ formatDate('2025-03-14') }} и получить «14 марта 2025 г.» без импорта.
Что подключается автоматически
| Откуда | Что |
|---|---|
| Vue | ref, computed, watch, onMounted и другие |
| Nuxt | useRoute, navigateTo, useFetch, useState и другие |
app/composables/ | Экспорты файлов верхнего уровня |
app/utils/ | Экспорты файлов верхнего уровня |
app/components/ | Компоненты |
Явный импорт тоже работает, если так понятнее: import { useLikes } from '~/composables/useLikes'.
Где вызывать composables
Composables Nuxt (useRoute, useFetch, useState) и ваши, которые их используют, вызывают в <script setup>, в другом composable, в middleware или плагине. Вызов внутри setTimeout или после await в обычной функции может закончиться ошибкой «A composable that requires access to the Nuxt instance was called outside of a plugin».
Частая ошибка
Nuxt просматривает только файлы верхнего уровня app/composables/. Файл app/composables/posts/usePosts.ts в подпапке автоматически не подключится, и шаблон выдаст ошибку usePosts is not defined. Держите composables прямо в папке или подключайте файл из подпапки явным импортом.