Pinia 状态管理利器:探秘 storeToRefs 的神奇魔力

1,470 阅读2分钟

当使用 Pinia 进行状态管理时,有一个非常有用的辅助函数叫做 storeToRefs。这个函数提供了一种简洁和便利的方式来将 store 中的状态转换为 ref 对象,使得状态在组件中的使用更加灵活和方便。

1. 什么是 storeToRefs ?

在 Pinia 中,storeToRefs 是一个用于将状态存储在 store 中转换为 ref 对象的辅助函数。通过使用 storeToRefs,可以将 store 中的状态直接暴露给组件,并且在模板中像普通的 ref 对象一样使用它们,而无需手动进行转换或者解构。

2. 常规解构与使用storeToRefs对比

2.1 常规解构
// stores/counter.js
// 导入一个方法 defineStore
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

// 抛出方法
export const useCounterStore = defineStore('counter',() => {
    // 定义数据 (state)
    const count = ref(0)

    // state定义修改数据方法 (action 同步)
    const increment = () => {
        count.value++
    }

    // getter定义
    const doubleCounter = computed(() => {
        return count.value * 2
    })

    // 以对象的方式return提供数组使用
    return { 
        count,
        increment,
        doubleCounter
        }
})
<template>
  <div>
    <button @click="counterStore.increment">{{ count }}</button>
    <p>{{ doubleCounter }}</p>
  </div>
</template>

<script setup>
// 1. 导入 useCounterStore 方法
import { useCounterStore } from '@/stores/counter.js'

// 2. 执行方法得到 store 实例对象
const counterStore = useCounterStore()

console.log(counterStore)
// 打印Proxy

// 直接解构赋值(会响应式丢失)
const { count, doubleCounter } =  counterStore
console.log(count, doubleCounter)

</script>
<style lang="scss" scoped>

</style>

结果:

image.png

从结果可以看出正常解构下得到的count, doubleCounter变量并不是响应式的,且在控制台上也只是打印俩个零,会响应式丢失。

2.2 storeToRefs
<template>
  <div>
    <button @click="increment">{{ count }}</button>
    <p>{{ doubleCounter }}</p>
  </div>
</template>

<script setup>
// 1. 导入 useCounterStore 方法
import { useCounterStore } from '@/stores/counter.js'
import { onMounted } from 'vue';
// 从 pinia 中导入 storeToRefs
import { storeToRefs } from 'pinia';

// 2. 执行方法得到 store 实例对象
const counterStore = useCounterStore()

console.log(counterStore)
// 打印Proxy

// 直接解构赋值(会响应式丢失)
// const { count, doubleCounter } =  counterStore
// console.log(count, doubleCounter)

// storeToRefs方法包裹(保持响应式更新)
const { count, doubleCounter } =  storeToRefs(counterStore)
console.log(count, doubleCounter)

// getter方法直接从原来的counterStore中解构赋值
const { increment } =  counterStore

</script>
<style lang="scss" scoped>
</style>

结果:

image.png

可以看出使用了storeToRefs方法后会保持响应式更新,且在控制台打印的结果中也是我们想要的响应式数据,而对于Pinia中的getter方法我们则无法继续通过storeToRefs来使用,这种情况下我们就可以使用解构来赋值使用。