Skip to main content
Практика завдань

Компоновані у Vue.js

Що таке Composables?

Composables — це функції, які використовують Composition API для інкапсуляції та повторного використання стану між компонентми.

Composables у Vue схожі на кастомні хуки у React.


Основний приклад

javascript
// useCounter.js import { ref } from 'vue' export function useCounter(initialValue = 0) { const count = ref(initialValue) function increment() { count.value++ } function decrement() { count.value-- } function reset() { count.value = initialValue } return { count, increment, decrement, reset } }

Використання:

javascript
<template> <div> <p>Count: {{ count }}</p> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="reset">Reset</button> </div> </template> <script setup> import { useCounter } from './useCounter' const { count, increment, decrement, reset } = useCounter(10) </script>

Конвенції іменування

Composables зазвичай називаються з префіксом use:

javascript
// Добре useCounter() useMouse() useFetch() useLocalStorage() // Погано counter() mouse() fetch()

Популярні приклади Composables

useMouse

Відстеження позиції миші:

javascript
// useMouse.js import { ref, onMounted, onUnmounted } from 'vue' export function useMouse() { const x = ref(0) const y = ref(0) function update(event) { x.value = event.pageX y.value = event.pageY } onMounted(() => { window.addEventListener('mousemove', update) }) onUnmounted(() => { window.removeEventListener('mousemove', update) }) return { x, y } }

useFetch

Отримання даних з API:

javascript
// useFetch.js import { ref } from 'vue' export function useFetch(url) { const data = ref(null) const error = ref(null) const loading = ref(false) async function fetch() { loading.value = true error.value = null try { const response = await window.fetch(url) data.value = await response.json() } catch (e) { error.value = e } finally { loading.value = false } } fetch() return { data, error, loading, refetch: fetch } }

useLocalStorage

Синхронізація з localStorage:

javascript
// useLocalStorage.js import { ref, watch } from 'vue' export function useLocalStorage(key, defaultValue) { const value = ref(defaultValue) // Читання з localStorage при ініціалізації const stored = localStorage.getItem(key) if (stored) { try { value.value = JSON.parse(stored) } catch (e) { console.error('Error parsing localStorage value:', e) } } // Збереження при зміні watch(value, (newValue) => { localStorage.setItem(key, JSON.stringify(newValue)) }, { deep: true }) return value }

Комбінування Composables

Composables можуть бути комбіновані:

javascript
// useUser.js import { useFetch } from './useFetch' import { useLocalStorage } from './useLocalStorage' export function useUser() { const userId = useLocalStorage('userId', null) const url = computed(() => userId.value ? `/api/users/${userId.value}` : null ) const { data: user, loading, error } = useFetch(url) function login(id) { userId.value = id } function logout() { userId.value = null } return { user, loading, error, login, logout } }

Найкращі практики

Повернення refs, а не reactive

javascript
// Добре export function useCounter() { const count = ref(0) return { count } } // Погано export function useCounter() { const state = reactive({ count: 0 }) return state }

Причина: refs зберігають реактивність при деструктуризації.

Очищення в onUnmounted

javascript
export function useEventListener(target, event, callback) { onMounted(() => { target.addEventListener(event, callback) }) onUnmounted(() => { target.removeEventListener(event, callback) }) }

Використовуйте toValue для гнучкості

javascript
import { toValue } from 'vue' export function useFetch(url) { // url може бути ref, computed або простим значенням const actualUrl = toValue(url) // ... }

Composables проти Mixins

Mixins (Vue 2)

javascript
// Погано - mixins const counterMixin = { data() { return { count: 0 } }, methods: { increment() { this.count++ } } }

Проблеми з Mixins:

  • Невизначене джерело властивостей
  • Конфлікти імен
  • Непрямі залежності

Composables (Vue 3)

javascript
// Добре - composables export function useCounter() { const count = ref(0) function increment() { count.value++ } return { count, increment } }

Переваги Composables:

  • Ясне джерело
  • Відсутність конфліктів імен
  • Краща типізація
  • Легше тестувати

Загальні помилки

Виклик composable поза setup

javascript
// Неправильно export default { data() { const { x, y } = useMouse() // Помилка! return { x, y } } } // Правильно export default { setup() { const { x, y } = useMouse() return { x, y } } }

Умовний виклик composable

javascript
// Неправильно if (condition) { const { count } = useCounter() // Помилка! } // Правильно const { count } = useCounter() if (condition) { // використати count }

Забування про очищення

javascript
// Неправильно - витік пам'яті export function useMouse() { const x = ref(0) function update(event) { x.value = event.pageX } window.addEventListener('mousemove', update) // Забули removeEventListener! return { x } } // Правильно export function useMouse() { const x = ref(0) function update(event) { x.value = event.pageX } onMounted(() => { window.addEventListener('mousemove', update) }) onUnmounted(() => { window.removeEventListener('mousemove', update) }) return { x } }

Висновок

Composables:

  • Повторювана логіка з Composition API
  • Краще, ніж mixins
  • Називаються з префіксом use
  • Повертають refs
  • Потребують очищення в onUnmounted
  • Можуть бути комбіновані
  • Підтримують TypeScript

На співбесідах:

Важливо вміти:

  • Пояснити, що таке composables і чому вони потрібні
  • Показати приклади створення composables
  • Описати переваги над mixins
  • Пояснити найкращі практики (іменування, очищення, повернення refs)
  • Навести приклади популярних composables

Зміст

Що таке Composables?Основний прикладКонвенції іменуванняПопулярні приклади ComposablesuseMouseuseFetchuseLocalStorageКомбінування ComposablesНайкращі практикиПовернення refs, а не reactiveОчищення в onUnmountedВикористовуйте toValue для гнучкостіComposables проти MixinsMixins (Vue 2)Composables (Vue 3)Загальні помилкиВиклик composable поза setupУмовний виклик composableЗабування про очищенняВисновок

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань