Skip to content

Робота з композиційними функціями

Композиційні функції - це функції, які використовують композиційний API Vue для інкапсуляції та повторного використання логіки стану. Незалежно від того, чи пишете ви власну, використовуєте зовнішні бібліотеки, чи робите і те, і інше, ви можете повністю використовувати потужність композиційних функцій у своїх сховищах pinia.

Опційні сховища

Визначаючи опційне сховище, ви можете викликати композиційну функцію всередині властивості state:

ts
export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: useLocalStorage('pinia/auth/login', 'bob'),
  }),
})
export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: useLocalStorage('pinia/auth/login', 'bob'),
  }),
})

Майте на увазі, що ви можете повернути лише стан, доступний для запису (наприклад, ref()). Ось кілька прикладів композиційних функцій, які можна використовувати:

Ось кілька прикладів композиційних функцій, які не можна використовувати в опційних сховищах (але можна використовувати з setup сховищами):

  • useMediaControls: розкриває функції
  • useMemoryInfo: розкриває дані лише для читання
  • useEyeDropper: відкриває дані та функції лише для читання

Setup сховища

З іншого боку, при визначенні setup сховища ви можете використовувати майже будь-які композиційні функції, оскільки кожна властивість розпізнається як стан, дія чи гетер:

ts
import { defineStore, skipHydrate } from 'pinia'
import { useMediaControls } from '@vueuse/core'

export const useVideoPlayer = defineStore('video', () => {
  // ми не розкриваємо цей елемент безпосередньо
  const videoElement = ref<HTMLVideoElement>()
  const src = ref('/data/video.mp4')
  const { playing, volume, currentTime, togglePictureInPicture } =
    useMediaControls(videoElement, { src })

  function loadVideo(element: HTMLVideoElement, src: string) {
    videoElement.value = element
    src.value = src
  }

  return {
    src,
    playing,
    volume,
    currentTime,

    loadVideo,
    togglePictureInPicture,
  }
})
import { defineStore, skipHydrate } from 'pinia'
import { useMediaControls } from '@vueuse/core'

export const useVideoPlayer = defineStore('video', () => {
  // ми не розкриваємо цей елемент безпосередньо
  const videoElement = ref<HTMLVideoElement>()
  const src = ref('/data/video.mp4')
  const { playing, volume, currentTime, togglePictureInPicture } =
    useMediaControls(videoElement, { src })

  function loadVideo(element: HTMLVideoElement, src: string) {
    videoElement.value = element
    src.value = src
  }

  return {
    src,
    playing,
    volume,
    currentTime,

    loadVideo,
    togglePictureInPicture,
  }
})

SSR

Коли ви маєте справу з Рендерингом на стороні серверу, вам потрібно подбати про деякі додаткові кроки, щоб використовувати композиційні функції у своїх сховищах.

У Опційних сховищах, вам треба визначити функцію hydrate(). Ця функція викликається, коли екземпляр сховища створюється на клієнті (браузері), коли на момент створення сховища доступний початковий стан. Причина, чому нам потрібно визначити цю функцію, полягає в тому, що в такому сценарії state() не викликається.

ts
import { defineStore, skipHydrate } from 'pinia'
import { useLocalStorage } from '@vueuse/core'

export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: useLocalStorage('pinia/auth/login', 'bob'),
  }),

  hydrate(state, initialState) {
    // у цьому випадку ми можемо повністю ігнорувати початковий стан, оскільки
    // ми хочемо прочитати значення з браузера
    state.user = useLocalStorage('pinia/auth/login', 'bob')
  },
})
import { defineStore, skipHydrate } from 'pinia'
import { useLocalStorage } from '@vueuse/core'

export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: useLocalStorage('pinia/auth/login', 'bob'),
  }),

  hydrate(state, initialState) {
    // у цьому випадку ми можемо повністю ігнорувати початковий стан, оскільки
    // ми хочемо прочитати значення з браузера
    state.user = useLocalStorage('pinia/auth/login', 'bob')
  },
})

У Setup сховищах, вам потрібно використовувати помічник під назвою skipHydrate() для будь-якої властивості стану, яку не слід отримувати з початкового стану. На відміну від сховищ параметрів, опційні сховища не можуть просто пропустити виклик state(), тому ми позначаємо властивості, які не можна гідратувати за допомогою skipHydrate(). Зверніть увагу, що це стосується лише реактивних властивостей, доступних для запису:

ts
import { defineStore, skipHydrate } from 'pinia'
import { useEyeDropper, useLocalStorage } from '@vueuse/core'

export const useColorStore = defineStore('colors', () => {
  const { isSupported, open, sRGBHex } = useEyeDropper()
  const lastColor = useLocalStorage('lastColor', sRGBHex)
  // ...
  return {
    lastColor: skipHydrate(lastColor), // Ref<string>
    open, // function
    isSupported, // boolean (навіть не реактивне)
  }
})
import { defineStore, skipHydrate } from 'pinia'
import { useEyeDropper, useLocalStorage } from '@vueuse/core'

export const useColorStore = defineStore('colors', () => {
  const { isSupported, open, sRGBHex } = useEyeDropper()
  const lastColor = useLocalStorage('lastColor', sRGBHex)
  // ...
  return {
    lastColor: skipHydrate(lastColor), // Ref<string>
    open, // function
    isSupported, // boolean (навіть не реактивне)
  }
})

Released under the MIT License.