浅谈 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 最稳)
相关推荐
接着奏乐接着舞。2 小时前
【2026年7月最新】69道RAG面试题
前端·人工智能·后端·aigc·embedding·rag
以和为贵2 小时前
前端也能搞懂 Agent:从 Function Calling 到自主编排
前端·人工智能·架构
风止何安啊3 小时前
🚦 前端并发请求 “交通管制”:别让你的接口堵成早高峰
前端·javascript·面试
J船长3 小时前
扫盲烂笔头:A 记录、CNAME 的作用, Nginx的用途,为啥叫反向代理
前端
妙码生花3 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(二十六):icon 组件封装
前端·vue.js·typescript
李明卫杭州3 小时前
Vue2 & Vue3 中 Router `props` 配置详解:彻底摆脱 `$route` 依赖
前端·vue.js·前端框架
掘金一周3 小时前
裁员了,公司很爽快,赔偿一分没少 | 沸点周刊 7.8
前端·人工智能·后端
熊猫钓鱼>_>3 小时前
2026 前端的三场底层革命:当 Vue、React Native 和 Three.js 同时去掉中间层
前端·javascript·vue.js·react native·架构·webgl·three.js
名字还没想好☜3 小时前
React useEffect 依赖数组踩坑:闭包陷阱与清理函数
前端·javascript·react.js·react·useeffect
宸翰4 小时前
uni-app 设置 Android 底部虚拟导航栏背景色
android·前端·uni-app