Getter 完全等同于 store 的 state 的計算值。可以通過 defineStore()
中的 getters
屬性來定義它們。推薦使用箭頭函數(shù),并且它將接收 state
作為第一個參數(shù):
export const useStore = defineStore('main', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
})
大多數(shù)時候,getter 僅依賴 state,不過,有時它們也可能會使用其他 getter。因此,即使在使用常規(guī)函數(shù)定義 getter 時,我們也可以通過 this
訪問到整個 store 實例,但(在 TypeScript 中)必須定義返回類型。這是為了避免 TypeScript 的已知缺陷,不過這不影響用箭頭函數(shù)定義的 getter,也不會影響不使用 this
的 getter。
export const useStore = defineStore('main', {
state: () => ({
count: 0,
}),
getters: {
// 自動推斷出返回類型是一個 number
doubleCount(state) {
return state.count * 2
},
// 返回類型**必須**明確設(shè)置
doublePlusOne(): number {
// 整個 store 的 自動補全和類型標注 ?
return this.doubleCount + 1
},
},
})
然后你可以直接訪問 store 實例上的 getter 了:
<script setup>
import { useCounterStore } from './counterStore'
const store = useCounterStore()
</script>
<template>
<p>Double count is {{ store.doubleCount }}</p>
</template>
與計算屬性一樣,你也可以組合多個 getter。通過 this
,你可以訪問到其他任何 getter。即使你沒有使用 TypeScript,你也可以用 JSDoc 來讓你的 IDE 提示類型。
export const useStore = defineStore('main', {
state: () => ({
count: 0,
}),
getters: {
// 類型是自動推斷出來的,因為我們沒有使用 `this`
doubleCount: (state) => state.count * 2,
// 這里我們需要自己添加類型(在 JS 中使用 JSDoc)
// 可以用 this 來引用 getter
/**
* 返回 count 的值乘以 2 加 1
*
* @returns {number}
*/
doubleCountPlusOne() {
// 自動補全 ?
return this.doubleCount + 1
},
},
})
Getter 只是幕后的計算屬性,所以不可以向它們傳遞任何參數(shù)。不過,你可以從 getter 返回一個函數(shù),該函數(shù)可以接受任意參數(shù):
export const useStore = defineStore('main', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId)
},
},
})
并在組件中使用:
<script setup>
import { useUserListStore } from './store'
const userList = useUserListStore()
const { getUserById } = storeToRefs(userList)
// 請注意,你需要使用 `getUserById.value` 來訪問
// <script setup> 中的函數(shù)
</script>
<template>
<p>User 2: {{ getUserById(2) }}</p>
</template>
請注意,當你這樣做時,getter 將不再被緩存,它們只是一個被你調(diào)用的函數(shù)。不過,你可以在 getter 本身中緩存一些結(jié)果,雖然這種做法并不常見,但有證明表明它的性能會更好:
export const useStore = defineStore('main', {
getters: {
getActiveUserById(state) {
const activeUsers = state.users.filter((user) => user.active)
return (userId) => activeUsers.find((user) => user.id === userId)
},
},
})
想要使用另一個 store 的 getter 的話,那就直接在 getter 內(nèi)使用就好:
import { useOtherStore } from './other-store'
export const useStore = defineStore('main', {
state: () => ({
// ...
}),
getters: {
otherGetter(state) {
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
setup()
時的用法 %{#usage-with-setup}%作為 store 的一個屬性,你可以直接訪問任何 getter(與 state 屬性完全一樣):
<script setup>
const store = useCounterStore()
store.count = 3
store.doubleCount // 6
</script>
在下面的例子中,你可以假設(shè)相關(guān)的 store 已經(jīng)創(chuàng)建了:
// 示例文件路徑:
// ./src/stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount(state) {
return state.count * 2
},
},
})
setup()
雖然并不是每個開發(fā)者都會使用組合式 API,但 setup()
鉤子依舊可以使 Pinia 在選項式 API 中更易用。并且不需要額外的映射輔助函數(shù)!
<script>
import { useCounterStore } from '../stores/counter'
export default defineComponent({
setup() {
const counterStore = useCounterStore()
return { counterStore }
},
computed: {
quadrupleCounter() {
return this.counterStore.doubleCount * 2
},
},
})
</script>
這在將組件從選項式 API 遷移到組合式 API 時很有用,但應(yīng)該只是一個遷移步驟,始終盡量不要在同一組件中混合兩種 API 樣式。
setup()
你可以使用前一節(jié)的 state 中的 mapState()
函數(shù)來將其映射為 getters:
import { mapState } from 'pinia'
import { useCounterStore } from '../stores/counter'
export default {
computed: {
// 允許在組件中訪問 this.doubleCount
// 與從 store.doubleCount 中讀取的相同
...mapState(useCounterStore, ['doubleCount']),
// 與上述相同,但將其注冊為 this.myOwnName
...mapState(useCounterStore, {
myOwnName: 'doubleCount',
// 你也可以寫一個函數(shù)來獲得對 store 的訪問權(quán)
double: store => store.doubleCount,
}),
},
}
更多建議: