浅谈 storeToRefs

概述

storeToRefs 是专门用来把 Pinia store 解构成「仍然有响应性 + 完整 TS 提示」的 refs 工具。


一、storeToRefs 是干嘛的?

问题背景

ts 复制代码
const store = useUserStore()
const { name } = store   // ❌ 响应性断了 + TS 变弱

解决方案

ts 复制代码
import { storeToRefs } from 'pinia'

const store = useUserStore()
const { name } = storeToRefs(store) // ✅

结果:

  • nameRef<string>
  • 响应性不丢
  • TS 自动补全、类型检查完整

二、它到底"帮你做了什么"?

storeToRefs(store) 会:

  1. 只处理

    1. state
    2. getters
  2. 跳过

    1. actions
  3. 把它们统一包成 ref / computed

可以把它理解成:

ts 复制代码
// 伪代码
{
  stateKey: toRef(store, 'stateKey'),
  getterKey: computed(() => store.getterKey),
}

三、TS 类型长什么样?

Store 定义

ts 复制代码
export const useUserStore = defineStore('user', {
  state: () => ({
    name: 'Tom',
    age: 18,
  }),
  getters: {
    isAdult: (state) => state.age >= 18,
  },
  actions: {
    setName(name: string) {
      this.name = name
    },
  },
})

使用 storeToRefs

ts 复制代码
const store = useUserStore()
const { name, age, isAdult } = storeToRefs(store)

TS 推导结果

ts 复制代码
name      // Ref<string>
age       // Ref<number>
isAdult   // ComputedRef<boolean>

✔ 不会是 any ✔ 不会丢 getter 类型 ✔ 自动区分 Ref / ComputedRef


四、为什么 actions 不能放进去?

ts 复制代码
const { setName } = storeToRefs(store) // ❌ 不存在

因为:

  • action 是普通函数
  • 不需要响应性
  • 包成 ref 反而会破坏 this / 调用方式

👉 正确做法:

ts 复制代码
const { setName } = store

五、最标准、最推荐的组合写法

ts 复制代码
const store = useUserStore()

const { name, age, isAdult } = storeToRefs(store)
const { setName } = store

这是 Pinia 官方文档 + 实战 都默认的模式。


六、模板里为什么不用 .value

ts 复制代码
<script setup lang="ts">
  const store = useUserStore()
  const { name } = storeToRefs(store)
</script>
<template>
  {{ name }} <!-- 自动 unref -->
</template>
  • Vue template 会自动 unref
  • TS 仍然认为它是 Ref<string>
  • 两边都正确 ✅

七、什么时候一定要用 storeToRefs

✅ 必须用

  • setup() / script setup 里解构 store
  • 想保留响应性 + TS 提示
  • 把 store 拆开传给 composable

❌ 不用

store.name store.isAdult store.setName()

不解构 = 不需要 storeToRefs


八、总结

Pinia 解构三原则

  • 解构 state / getters 👉 storeToRefs
  • 解构 actions 👉 直接解
  • 能不解构就不解构(TS 最稳)
相关推荐
还有多久拿退休金12 小时前
dnd-kit 碰撞检测算法:你的订单为什么自己"跑"到了 1 号?
前端
qq_3168377512 小时前
npm run tauri build Downloading下载超时
前端·npm·node.js
w_t_y_y12 小时前
VUE3(二)VUE2和VUE3区别
前端·javascript·vue.js
T-shmily12 小时前
使用svg图标
前端·css
阿明在折腾12 小时前
在浏览器里实现 PDF 合并与拆分:pdf-lib 实战指南
前端·javascript
米高梅狮子12 小时前
03.OpenStack使用
linux·前端·云原生·容器·架构·kubernetes·openstack
时光不负努力12 小时前
手写三大核心:Promise、Event Bus、深拷贝
前端
星栈12 小时前
被Leptos弹窗逼疯后,我搞了一套零Props方案
前端·前端框架·全栈
不是山谷.:.12 小时前
Axios的【接口防抖 + 请求失败重试 + 弱网提示】三合一高阶版封装
前端·javascript·vue.js·笔记·elementui·typescript
超绝大帅哥12 小时前
babel降级|>, Object.groupBy
前端·javascript