浅谈 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) // ✅

结果:

  • name 是 Ref<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 最稳)
相关推荐
大文说跨境4 分钟前
多账号环境隔离方案技术选型:指纹浏览器、VPS 与云手机的三种架构对比
java·开发语言·前端
咕白m6256 分钟前
使用 C# 将 TIFF 转换为 PDF
前端·c#
全栈项目管理程序猿9 分钟前
ArcGIS JS 基础教程(28):图层渲染顺序管理
前端·javascript
huakoh12 分钟前
MCP 工具报错走哪条通道:三条探针的最小复现检查
前端
用户0333074139519 分钟前
ParadeDB 的 pg_search 0.26 把十词 BM25 搜索从 129ms 降到 29ms
前端
不爱说话郭德纲29 分钟前
从“点点点”到一键出包:我把 uni-app x Android 离线打包做成了脚本
android·前端·uni-app
Lstone736435 分钟前
从 Jetpack Compose 到 CMP:跨平台开发学习笔记
前端
deli00740 分钟前
多加一粒沙,整堆为什么就塌了?sandpile 模型 20 万粒实测
前端
涛涛ing41 分钟前
乱序HTML流正式进入浏览器:前端流式渲染的“框架特权”被终结了
前端
__sjfzllv___42 分钟前
在职前端Leader学习/转行 AI Agent -DAY73
前端