Робота з композиційними функціями
Композиційні функції - це функції, які використовують композиційний API Vue для інкапсуляції та повторного використання логіки стану. Незалежно від того, чи пишете ви власну, використовуєте зовнішні бібліотеки, чи робите і те, і інше, ви можете повністю використовувати потужність композиційних функцій у своїх сховищах pinia.
Опційні сховища
Визначаючи опційне сховище, ви можете викликати композиційну функцію всередині властивості state
:
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 сховища ви можете використовувати майже будь-які композиційні функції, оскільки кожна властивість розпізнається як стан, дія чи гетер:
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()
не викликається.
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()
. Зверніть увагу, що це стосується лише реактивних властивостей, доступних для запису:
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 (навіть не реактивне)
}
})