《Pinia实战》4.核心概念 Getter

欢迎观看《Pinia实战》视频课程

    1. Getter
      1. Getter

Getter 完全等同于 store 的 state 的计算值。可以通过 defineStore() 中的 getters 属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数:

export const useCounterStore = defineStore('counter', {

  state: () => ({

    count: 0,

  }),

  getters: {

    doubleCount: (state) => state.count * 2,

  },

})

大多数时候,getter 仅依赖 state。不过,有时它们也可能会使用其他 getter。因此,即使在使用常规函数定义 getter 时,我们也可以通过 this 访问到整个 store 实例,但(在 TypeScript 中)必须定义返回类型。这是为了避免 TypeScript 的已知缺陷,不过这不影响用箭头函数定义的 getter,也不会影响不使用 this 的 getter。

export const useCounterStore = defineStore('counter', {

  state: () => ({

    count: 0,

  }),

  getters: {

    // 自动推断出返回类型是一个 number

    doubleCount(state) {

      return state.count * 2

    },

    // 返回类型**必须**明确设置

    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>

      1. 访问其他 getter

与计算属性一样,你也可以组合多个 getter。通过 this,你可以访问到其他任何 getter。在这种情况下,你需要为这个 getter 指定一个返回值的类型。

counterStore.ts

export const useCounterStore = defineStore('counter', {

  state: () => ({

    count: 0,

  }),

  getters: {

    doubleCount(state) {

      return state.count * 2

    },

    doubleCountPlusOne(): number {

      return this.doubleCount + 1

    },

  },

})

counterStore.js

// 你可以在 JavaScript 中使用 JSDoc (https://jsdoc.app/tags-returns.html)

export const useCounterStore = defineStore('counter', {

  state: () => ({

    count: 0,

  }),

  getters: {

    // 类型是自动推断出来的,因为我们没有使用 `this`

    doubleCount: (state) => state.count * 2,

    // 这里我们需要自己添加类型(在 JS 中使用 JSDoc)

    // 可以用 this 来引用 getter

    /**

     * 返回 count 的值乘以 2 加 1

     *

     * @returns {number}

     */

    doubleCountPlusOne() {

      // 自动补全 ✨

      return this.doubleCount + 1

    },

  },

})

      1. 向 getter 传递参数

Getter 只是幕后的计算属性,所以不可以向它们传递任何参数。不过,你可以从 getter 返回一个函数,该函数可以接受任意参数:

export const useUserListStore = defineStore('userList', {

  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> 中的函数

</script>

<template>

  <p>User 2: {{ getUserById(2) }}</p>

</template>

请注意,当你这样做时,getter 将不再被缓存。它们只是一个被你调用的函数。不过,你可以在 getter 本身中缓存一些结果,虽然这种做法并不常见,但有证明表明它的性能会更好:

export const useUserListStore = defineStore('userList', {

  getters: {

    getActiveUserById(state) {

      const activeUsers = state.users.filter((user) => user.active)

      return (userId) => activeUsers.find((user) => user.id === userId)

    },

  },

})

      1. 访问其他 store 的 getter

想要使用另一个 store 的 getter 的话,那就直接在 getter 内使用就好:

import { useOtherStore } from './other-store'

export const useStore = defineStore('main', {

  state: () => ({

    // ...

  }),

  getters: {

    otherGetter(state) {

      const otherStore = useOtherStore()

      return state.localData + otherStore.data

    },

  },

})

      1. 使用 setup() 时的用法

作为 store 的一个属性,你可以直接访问任何 getter(与 state 属性完全一样):

<script setup>

const store = useCounterStore()

store.count = 3

store.doubleCount // 6

</script>

      1. 使用选项式 API 的用法

在下面的例子中,你可以假设相关的 store 已经创建了:

// 示例文件路径:

// ./src/stores/counter.js

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {

  state: () => ({

    count: 0,

  }),

  getters: {

    doubleCount(state) {

      return state.count * 2

    },

  },

})

        1. 使用 setup()

虽然并不是每个开发者都会使用组合式 API,但 setup() 钩子依旧可以使 Pinia 在选项式 API 中更易用。并且不需要额外的映射辅助函数!

<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 时很有用,但应该只是一个迁移步骤。始终尽量不要在同一组件中混合两种 API 样式。

        1. 不使用 setup()

你可以使用前一节的 state 中的 mapState() 函数来将其映射为 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',

      // 你也可以写一个函数来获得对 store 的访问权

      double: (store) => store.doubleCount,

    }),

  },

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值