Composables

↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая

Обязательно~4 мин чтенияУровень: middle

Зачем это на собесе

Composables — способ переиспользования логики; смотрят на именование, реактивные аргументы и очистку.

Объяснение

Composable — функция с префиксом use, инкапсулирующая состояние и логику с реактивностью (вызывается в setup).

// useFetch.ts
export function useFetch<T>(url: MaybeRefOrGetter<string>) {
  const data = shallowRef<T | null>(null);
  const error = ref<Error | null>(null);
  const loading = ref(false);
  let ctrl: AbortController | undefined;
 
  async function run() {
    ctrl?.abort(); ctrl = new AbortController();
    loading.value = true; error.value = null;
    try {
      const res = await fetch(toValue(url), { signal: ctrl.signal });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      data.value = await res.json();
    } catch (e) { if ((e as Error).name !== "AbortError") error.value = e as Error; }
    finally { loading.value = false; }
  }
 
  watchEffect(run);                                     // повторный запрос при смене url
  onScopeDispose(() => ctrl?.abort());                  // очистка при уничтожении области
  return { data, error, loading, refresh: run };
}
 
// Использование
const { data: orders, loading } = useFetch<Order[]>(() => `/api/orders?page=${page.value}`);

Соглашения:

  • Имя useXxx; файл useXxx.ts.
  • Входные параметры: принимайте MaybeRefOrGetter и читайте через toValue — реактивные и обычные значения работают одинаково.
  • Возвращаемое значение: объект refs (легко деструктурируется без потери реактивности).
  • Побочные эффекты и очистка: onScopeDispose/onUnmounted, watch с onCleanup.
  • Состояние: локальное (создаётся при каждом вызове) или общее (модульная область — синглтон; для общего лучше Pinia).
  • Не принимайте компонентный контекст неявно; хуки жизненного цикла требуют вызова в setup.

Примеры: useToggle, useDebounce, usePagination, useForm, useAuth, useMediaQuery, useInfiniteScroll.

Composables vs альтернативы:

ПодходПроблема / особенность
Миксинынеявные источники, конфликты имён
Renderless-компонентылишний слой компонентов
Утилитыбез реактивности
Piniaглобальное состояние и DevTools

Нюансы и подводные камни

  • Composable с хуками, вызванный вне setup/асинхронно после await, теряет контекст.
  • Синглтон-состояние в модуле — проблема для SSR (общее между запросами).
  • Не возвращайте reactive-объект, который придётся деструктурировать.
  • Тестируйте composables как обычные функции (withSetup хелпер, mount обёртка).

Практика

  1. Напишите useDebouncedRef, usePagination, useLocalStorage.
  2. Сделайте useFetch с отменой и повторными запросами.
  3. Протестируйте composable с фейковыми таймерами.

Вопросы с ответами

Связанные темы