組合式函數(shù)是利用 Vue 組合式 API 來(lái)封裝和復(fù)用有狀態(tài)邏輯的函數(shù)。無(wú)論你是自己寫,還是使用外部庫(kù),或者兩者都有,你都可以在 pinia store 中充分發(fā)揮組合式函數(shù)的力量。
當(dāng)定義一個(gè) option store 時(shí),你可以在 state
屬性中調(diào)用組合式函數(shù):
export const useAuthStore = defineStore('auth', {
state: () => ({
user: useLocalStorage('pinia/auth/login', 'bob'),
}),
})
請(qǐng)記住,你只能返回可寫的狀態(tài) (例如,一個(gè) ref()
) 。下面是一些可用的組合式函數(shù)的示例:
下面是一些不可在 option store 中使用的組合式函數(shù) (但可在 setup store 中使用) :
另外,當(dāng)定義一個(gè) setup store 時(shí),你幾乎可以使用任何組合式函數(shù),因?yàn)槊恳粋€(gè)屬性都會(huì)被辨別為 state 、action 或者 getter:
import { defineStore, skipHydrate } from 'pinia'
import { useMediaControls } from '@vueuse/core'
export const useVideoPlayer = defineStore('video', () => {
// 我們不會(huì)直接暴露這個(gè)元素
const videoElement = ref<HTMLVideoElement>()
const src = ref('/data/video.mp4')
const { playing, volume, currentTime, togglePictureInPicture } =
useMediaControls(video, { src })
function loadVideo(element: HTMLVideoElement, src: string) {
videoElement.value = element
src.value = src
}
return {
src,
playing,
volume,
currentTime,
loadVideo,
togglePictureInPicture,
}
})
當(dāng)處理服務(wù)端渲染時(shí),你有一些需要額外注意的內(nèi)容,以便在 store 中使用組合式函數(shù)。
在 Option Store 中,你需要定義一個(gè) hydrate()
函數(shù)。當(dāng) store 在客戶端 (瀏覽器) 上被實(shí)例化的過(guò)程中,創(chuàng)建 store 時(shí)有一個(gè)可用的初始狀態(tài)時(shí),這個(gè)函數(shù)就會(huì)被調(diào)用。我們需要定義這個(gè)函數(shù)的原因是,在這種情況下,state()
是不會(huì)被調(diào)用的。
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) {
// 在這種情況下,我們可以完全忽略初始狀態(tài)
// 因?yàn)槲覀兿霃臑g覽器中讀取數(shù)值。
state.user = useLocalStorage('pinia/auth/login', 'bob')
},
})
在 Setup Store 中,對(duì)于任何不應(yīng)該從初始狀態(tài)中接收的 state 屬性 你都需要使用一個(gè)名為 skipHydrate()
的輔助函數(shù)。與 option store 不同,setup store 不能直接跳過(guò)調(diào)用 state()
,所以我們用 skipHydrate()
標(biāo)記那些不能被激活的屬性。請(qǐng)注意,這只適用于可寫的響應(yīng)式屬性:
import { defineStore, skipHydrate } from 'pinia'
import { useEyeDropper, useLocalStorage } from '@vueuse/core'
const useColorStore = defineStore('colors', () => {
const { isSupported, open, sRGBHex } = useEyeDropper()
const lastColor = useLocalStorage('lastColor', sRGBHex)
// ...
return {
lastColor: skipHydrate(lastColor), // Ref<string>
open, // Function
isSupported, // boolean (非響應(yīng)式)
}
})
更多建議: