获取器
获取器与 Store 状态的 计算属性 完全等效。它们可以在 defineStore()
中使用 getters
属性定义。它们接收 state
作为第一个参数,以 鼓励 使用箭头函数
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
})
大多数情况下,获取器只会依赖于状态。但是,它们可能需要使用其他获取器。因此,在定义常规函数时,我们可以通过 this
访问 整个 Store 实例,但必须定义返回类型的类型(在 TypeScript 中)。这是由于 TypeScript 中的一个已知限制,并且 不会影响使用箭头函数定义的获取器或不使用 this
的获取器
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
// automatically infers the return type as a number
doubleCount(state) {
return state.count * 2
},
// the return type **must** be explicitly set
doublePlusOne(): number {
// autocompletion and typings for the whole store ✨
return this.doubleCount + 1
},
},
})
然后,您可以直接在 Store 实例上访问获取器
<script setup>
import { useCounterStore } from './counterStore'
const store = useCounterStore()
</script>
<template>
<p>Double count is {{ store.doubleCount }}</p>
</template>
访问其他获取器
与计算属性一样,您可以组合多个获取器。通过 this
访问任何其他获取器。在这种情况下,您需要为获取器指定一个返回类型。
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount(state) {
return state.count * 2
},
doubleCountPlusOne(): number {
return this.doubleCount + 1
},
},
})
// You can use JSDoc (https://jsdoc.node.org.cn/tags-returns.html) in JavaScript
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
// type is automatically inferred because we are not using `this`
doubleCount: (state) => state.count * 2,
// here we need to add the type ourselves (using JSDoc in JS). We can also
// use this to document the getter
/**
* Returns the count value times two plus one.
*
* @returns {number}
*/
doubleCountPlusOne() {
// autocompletion ✨
return this.doubleCount + 1
},
},
})
向获取器传递参数
获取器 只是幕后 计算 属性,因此无法向它们传递任何参数。但是,您可以从 获取器 返回一个函数来接受任何参数
export const useStore = defineStore('main', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId)
},
},
})
并在组件中使用
<script setup>
import { storeToRefs } from 'pinia'
import { useUserListStore } from './store'
const userList = useUserListStore()
const { getUserById } = storeToRefs(userList)
// note you will have to use `getUserById.value` to access
// the function within the <script setup>
</script>
<template>
<p>User 2: {{ getUserById(2) }}</p>
</template>
请注意,在执行此操作时,获取器不再被缓存。它们只是您调用的函数。但是,您可以在获取器本身内部缓存一些结果,这并不常见,但应该会提高性能
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 的获取器
要使用另一个 Store 的获取器,您可以直接在 获取器 内部 使用它
import { useOtherStore } from './other-store'
export const useStore = defineStore('main', {
state: () => ({
// ...
}),
getters: {
otherGetter(state) {
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
与 setup()
一起使用
您可以直接将任何获取器作为 Store 的属性访问(与状态属性完全相同)
<script setup>
const store = useCounterStore()
store.count = 3
store.doubleCount // 6
</script>
与选项 API 一起使用
对于以下示例,您可以假设创建了以下 Store
// Example File Path:
// ./src/stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount(state) {
return state.count * 2
},
},
})
使用 setup()
虽然 Composition API 并非适合所有人,但 setup()
钩子可以使 Pinia 在选项 API 中更容易使用。无需额外的映射辅助函数!
<script>
import { useCounterStore } from '../stores/counter'
export default defineComponent({
setup() {
const counterStore = useCounterStore()
// **only return the whole store** instead of destructuring
return { counterStore }
},
computed: {
quadrupleCounter() {
return this.counterStore.doubleCount * 2
},
},
})
</script>
这在将组件从选项 API 迁移到 Composition API 时很有用,但 应该只是一个迁移步骤。始终尝试不要在同一个组件中混合两种 API 样式。
无需 setup()
您可以使用与 状态的上一节 中使用的相同 mapState()
函数来映射到获取器
import { mapState } from 'pinia'
import { useCounterStore } from '../stores/counter'
export default {
computed: {
// gives access to this.doubleCount inside the component
// same as reading from store.doubleCount
...mapState(useCounterStore, ['doubleCount']),
// same as above but registers it as this.myOwnName
...mapState(useCounterStore, {
myOwnName: 'doubleCount',
// you can also write a function that gets access to the store
double: (store) => store.doubleCount,
}),
},
}