Что такое composables в Nuxt и как их использовать правильно?

MiddleNuxt.js #nuxt #composables

Вопрос

Что такое composables в Nuxt и какие правила стоит соблюдать при их написании?

Короткий ответ

Composables — это функции useXxx(), инкапсулирующие переиспользуемую реактивную логику. В Nuxt все файлы из папки composables/ автоматически доступны в компонентах без импорта.

Подробный ответ

Composable — обычная JS/TS-функция, использующая реактивные примитивы Vue (ref, computed, watch) и, при необходимости, Nuxt-composables (useState, useFetch, useRoute).

Ключевые правила:

  • Имя должно начинаться с use — это конвенция, по которой ESLint plugin для Vue понимает, что внутри можно вызывать другие композаблы/хуки.
  • Composable должен вызываться на верхнем уровне <script setup> (или другого composable), а не внутри if/циклов — иначе может нарушиться привязка реактивности к текущему компоненту.
  • Для состояния, которое должно быть общим для всего приложения и safe для SSR, используется useState('key', () => initialValue) — обычный ref вне компонента в SSR "утечёт" между запросами разных пользователей.
  • Composable, работающий с данными (загрузка, кэширование), — хорошее место, чтобы спрятать useFetch/queryCollection и вернуть компоненту уже готовые, типизированные данные.

Пример

// composables/useMediaQuery.ts
export function useMediaQuery(query: string) {
  const matches = ref(false)

  onMounted(() => {
    const mql = window.matchMedia(query)
    matches.value = mql.matches
    const listener = (e: MediaQueryListEvent) => { matches.value = e.matches }
    mql.addEventListener('change', listener)
    onUnmounted(() => mql.removeEventListener('change', listener))
  })

  return matches
}
<script setup>
const isMobile = useMediaQuery('(max-width: 768px)')
</script>

Дополнительные вопросы

  • Почему обычный ref вне компонента небезопасен для SSR, а useState — нет?
  • Как тестировать composable отдельно от компонента?
  • Можно ли вызвать один composable внутри другого?

Связанные вопросы