目标:把 Pinia 的两种写法讲透,写明“怎么写、怎么用、怎么选、各自优缺点与典型场景”。全文配完整代码与注意事项,可直接当团队规范参考。


一、背景与准备

  • 适用版本:Vue 3 + Pinia 2.x
  • 安装与初始化:
# 安装
npm i pinia# main.ts/main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'const app = createApp(App)
app.use(createPinia())
app.mount('#app')

Pinia 提供两种定义 Store 的方式:

  • Options Store(配置式):写法类似 Vuex,结构清晰,学习成本低。
  • Setup Store(组合式):写法与 Composition API 一致,灵活可复用,能直接使用 refcomputedwatch、自定义 composable。

下面分别实现 同一个业务:计数器 + 异步拉取用户信息,用两种写法各做一遍,再对比差异与使用场景。


二、Options Store(配置式)

2.1 定义

// stores/counter.ts
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {// 1) state:必须是函数,返回对象;可被 DevTools 追踪、可序列化state: () => ({count: 0,user: null as null | { id: number; name: string }}),// 2) getters:类似计算属性,支持缓存与依赖追踪getters: {double: (state) => state.count * 2,welcome(state) {return state.user ? `Hi, ${state.user.name}` : 'Guest'}},// 3) actions:业务方法,支持异步;这里的 this 指向 store 实例actions: {increment() {this.count++},reset() {this.$reset()},async fetchUser() {// 模拟请求await new Promise((r) => setTimeout(r, 400))this.user = { id: 1, name: 'Tom' }}}
})

注意:在 actions 里不要用箭头函数,否则 this 不指向 store;如果必须用箭头函数,改为显式引用 useCounterStore() 返回的实例。

2.2 组件中使用

<script setup lang="ts">
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'const counter = useCounterStore()
// 解构 state/getters 请用 storeToRefs,保持解构后的值仍具备响应性
const { count, double, welcome, user } = storeToRefs(counter)function add() {counter.increment()
}function load() {counter.fetchUser()
}
</script><template><div class="card"><p>count: {{ count }}</p><p>double: {{ double }}</p><p>{{ welcome }}</p><button @click="add">+1</button><button @click="load">拉取用户</button></div>
</template>

2.3 进阶用法

const counter = useCounterStore()// 批量更新(避免多次触发)
counter.$patch({ count: counter.count + 2, user: { id: 2, name: 'Jerry' } })// 监听状态变化(持久化/日志)
const unsubscribe = counter.$subscribe((mutation, state) => {// mutation.type: 'direct' | 'patch object' | 'patch function'// 可在这里做本地存储localStorage.setItem('counter', JSON.stringify(state))
})// 监听 action 调用链
counter.$onAction(({ name, args, onAfter, onError }) => {console.time(name)onAfter(() => console.timeEnd(name))onError((e) => console.error('[action error]', name, e))
})

优点小结(Options Store)

  • 结构化:state/getters/actions 职责清晰、易读易管控。
  • 迁移友好:从 Vuex 迁移几乎零心智负担。
  • 可序列化:state 天生适合被 DevTools/SSR 序列化与持久化插件处理。
  • this 能直达 getters/state,写法直观(注意不要箭头函数)。

注意点

  • 需要通过 this 访问 store(对 TS “this” 的类型提示依赖更强)。
  • getters 中不要产生副作用;复杂逻辑建议放到 actions

三、Setup Store(组合式)

3.1 定义

// stores/counter-setup.ts
import { defineStore } from 'pinia'
import { ref, computed, watch } from 'vue'export const useCounterSetup = defineStore('counter-setup', () => {// 1) 直接用 Composition APIconst count = ref(0)const user = ref<null | { id: number; name: string }>(null)const double = computed(() => count.value * 2)const welcome = computed(() => (user.value ? `Hi, ${user.value.name}` : 'Guest'))// 2) 方法就写普通函数(无 this,更易测试/复用)function increment() {count.value++}function reset() {count.value = 0user.value = null}async function fetchUser() {await new Promise((r) => setTimeout(r, 400))user.value = { id: 1, name: 'Tom' }}// 3) 可直接使用 watch 等组合式能力watch(count, (v) => {if (v > 10) console.log('count 很大了')})// 4) 返回对外可用的成员return { count, user, double, welcome, increment, reset, fetchUser }
})

3.2 组件中使用

<script setup lang="ts">
import { storeToRefs } from 'pinia'
import { useCounterSetup } from '@/stores/counter-setup'const store = useCounterSetup()
const { count, double, welcome, user } = storeToRefs(store)function add() {store.increment()
}
</script><template><div class="card"><p>count: {{ count }}</p><p>double: {{ double }}</p><p>{{ welcome }}</p><button @click="add">+1</button><button @click="store.fetchUser()">拉取用户</button><button @click="store.reset()">重置</button></div>
</template>

3.3 进阶用法(复用逻辑 & 外部 composable)

// composables/usePersist.ts(示例)
import { watch } from 'vue'
export function usePersist<T extends object>(key: string, state: T) {watch(() => state,(val) => localStorage.setItem(key, JSON.stringify(val)),{ deep: true })
}// stores/profile.ts - 在 Setup Store 里直接用组合函数
import { defineStore } from 'pinia'
import { reactive, computed } from 'vue'
import { usePersist } from '@/composables/usePersist'export const useProfile = defineStore('profile', () => {const form = reactive({ name: '', age: 0 })const valid = computed(() => form.name.length > 0 && form.age > 0)usePersist('profile', form)return { form, valid }
})

优点小结(Setup Store)

  • 灵活:原生 Composition API 能力全开(ref/computed/watch/async/自定义 composable)。
  • 可复用:把复杂业务拆到多个 composable,再组合进 store。
  • 更易测试:普通函数、无 this 语义,单元测试与类型推断更直观。

注意点

  • 返回的成员必须显式 return,未返回的属性对外不可见。
  • 非可序列化的值(如函数、Map、类实例)放入 state 时需考虑 SSR/持久化的影响。

四、两种写法如何选?(场景对比)

维度Options Store(配置式)Setup Store(组合式)
上手成本低,结构固定,接近 Vuex中等,需要熟悉 Composition API
代码组织三段式清晰:state/getters/actions任意组织,更灵活,也更考验规范
逻辑复用依赖抽出到独立函数/插件直接用 composable,自然拼装
this 使用actions 里有 this,直达 state/getters无 this,纯函数,易测试
TypeScript对 this 的类型推断要注意类型自然跟随 ref/reactive
DevTools/序列化天然友好(state 可序列化)取决于返回的成员是否可序列化
典型场景业务中小、逻辑清晰、团队从 Vuex 迁移中大型、复合逻辑、强复用/抽象需求

选择建议

  • 团队以简单业务/快速落地/从 Vuex 迁移为主 → 优先 Options Store
  • 团队重组合式、强调复用与抽象,或需要在 store 内使用 watch / 自定义 composable → 选择 Setup Store
  • 实际项目中可以混用:简单模块用 Options,复杂域(如表单域、编辑器域)用 Setup。

五、最佳实践清单

  1. 永远用 storeToRefs 解构:保持解构后仍具备响应性。
  2. 批量更新用 $patch:一次性修改多个字段,减少触发次数。
  3. 持久化:使用插件 @pinia/plugin-persistedstate 或自写 $subscribe 落地。
  4. SSR:每次请求都要创建新的 pinia 实例;避免向 state 放入不可序列化的“大对象”。
  5. 跨 Store 调用:在 action 内部调用另一个 store,按需引入,避免循环依赖。
  6. 命名规范stores/模块名.ts,导出 useXxxStore/useXxxSetup 等有语义的命名。

六、从 Vuex 迁移到 Pinia(速查)

VuexPinia(Options)
statestate() { return { … } }
gettersgetters: { double: (s)=>s.count*2 }
mutationsactions(同步/异步都放 actions)
actions仍然是 actions
mapState/mapGetters直接 storeToRefs(useStore()) 解构

迁移时最常见问题:丢失响应性。记得使用 storeToRefs,或在模板中直接用 store.count 不解构。


七、常见坑位与排查

  • 解构丢响应性const { count } = useStore() ❌ → const { count } = storeToRefs(useStore())
  • actions 用了箭头函数导致 this 丢失(Options):改普通函数或显式引用 store。
  • 在 getters 里写副作用:应移到 action 或 watch。
  • 循环依赖:跨 store 调用时注意 import 时机,可在 action 内部按需调用另一个 store。
  • SSR 水合失败:state 内含不可序列化值;或客户端初始 state 与服务端不一致。

八、结语

Options Store 强在“结构化与可维护”,Setup Store 胜在“灵活与复用”。
选型的关键不是“谁更先进”,而是“当前问题需要哪种力量”。理解两种写法的边界与优势,团队协作会更顺手、代码也更可持续。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/98136.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/98136.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/98136.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

setup函数相关【3】

目录1.setup函数&#xff1a;1.概述&#xff1a;2.案例分析&#xff1a;2.setup函数的优化&#xff1a;&#xff08;setup语法糖&#xff09;优化1&#xff1a;优化2&#xff1a;安装插件&#xff1a;安装指令&#xff1a;只对当前项目安装配置vite.config.ts&#xff1a;代码编…

如何通过AI进行数据资产梳理

最终产出 数据资产清单 包含所有数据资产的详细目录,列出数据集名称、描述、所有者、格式、存储位置和元数据。 用途:帮助政府部门清晰了解数据资产分布和状态。 数据质量报告 数据质量评估结果,记录准确性、完整性、一致性等问题及改进建议,基于政府认可的数据质量框架(如…

【传奇开心果系列】Flet框架结合pillow实现的英文文字倒映特效自定义模板特色和实现原理深度解析

Flet框架结合pillow实现的英文文字倒映特效自定义模板特色和实现原理深度解析 一、效果展示截图 二、使用场景 三、特色说明 四、概括说明 五、依赖文件列表 六、安装依赖命令 七、 项目结构建议 八、注意事项 九、Flet 文字倒影效果实现原理分析 (一)组件结构与功能 1. 图像…

2025最新深度学习面试必问100题--理论+框架+原理+实践 (下篇)

2025最新深度学习面试必问100题–理论框架原理实践 (下篇) 在上篇中&#xff0c;我们已经深入探讨了机器学习基础、CNN、RNN及其变体&#xff0c;以及模型优化的核心技巧。 在下篇中&#xff0c;我们将把目光投向更远方&#xff0c;聚焦于当今AI领域最炙手可热的前沿。我们将深…

原子工程用AC6编译不过问题

…\Output\atk_h750.axf: Error: L6636E: Pre-processor step failed for ‘…\User\SCRIPT\qspi_code.scf.scf’修改前&#xff1a; #! armcc -E ;#! armclang -E --targetarm-arm-none-eabi -mcpucortex-m7 -xc /* 使用说明 ! armclang -E --targetarm-arm-none-eabi -mcpuco…

Python有哪些经典的常用库?(第一期)

目录 1、NumPy (数值计算基础库) 核心特点&#xff1a; 应用场景&#xff1a; 代码示例&#xff1a; 2、Pandas (数据分析处理库) 应用场景&#xff1a; 代码示例&#xff1a; 3、Scikit-learn (机器学习库) 核心特点&#xff1a; 应用场景&#xff1a; 代码示例&am…

现代 C++ 高性能程序驱动器架构

&#x1f9e0; 现代 C 高性能程序驱动器架构M/PA&#xff08;多进程&#xff09;是隔离的“孤岛”&#xff0c;M/TA&#xff08;多线程&#xff09;是共享的“战场”&#xff0c;EDSM&#xff08;事件驱动&#xff09;是高效的“反应堆”&#xff0c;MDSM&#xff08;消息驱动&…

投资储能项目能赚多少钱?小程序帮你测算

为解决电网负荷平衡、提升新能源消纳等问题&#xff0c;储能项目的投资开发越来越多。那么&#xff0c;投资储能项目到底能赚多少钱&#xff1f;适不适合投资&#xff1f;用“绿虫零碳助手”3秒钟精准测算。操作只需四步&#xff0c;简单易懂&#xff1a;1.快速登录&#xff1a…

Mac 能够连Wife,但是不能上网问题解决

请按照以下步骤从最简单、最可能的原因开始尝试&#xff1a; 第一步&#xff1a;基础快速排查 这些步骤能解决大部分临时性的小故障。 重启设备&#xff1a;关闭您的 Mac 和路由器&#xff0c;等待一分钟后再重新打开。这是解决网络问题最有效的“万能药”。检查其他设备&am…

基于SpringBoot的旅游管理系统的设计与实现(代码+数据库+LW)

摘要 本文阐述了一款基于SpringBoot框架的旅游管理系统设计与实现。该系统整合了用户信息管理、旅游资源展示、订单处理流程及安全保障机制等核心功能&#xff0c;专为提升旅游行业的服务质量和运营效率而设计。 系统采用前后端分离架构&#xff0c;前端界面设计注重跨设备兼…

Springboot乐家流浪猫管理系统16lxw(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能&#xff1a;领养人,流浪猫,领养申请开题报告内容基于Spring Boot的乐家流浪猫管理系统开题报告一、研究背景与意义随着城市化进程加速和人口增长&#xff0c;流浪猫问题已成为全球性社会挑战。据统计&#xff0c;全球每年约有1.5亿只无家可归的宠物&a…

函数定义跳转之代码跳转

相信大家在开发的过程中都有用到函数定义跳转的功能&#xff0c;在 IDE 中&#xff0c;如果在函数调用的地方停留光标&#xff0c;可能会提示对应的函数定义&#xff0c;在 GitHub 中也是如此&#xff0c;对于一些仓库来说&#xff0c;我们可以直接查看对应的函数定义了&#x…

探讨Xsens在人形机器人研发中的四个核心应用

探索Xsens动作捕捉如何改变人形机器人研发——使机器人能够从人类运动中学习、更直观地协作并弥合模拟与现实世界之间的差距。人形机器人技术是当今世界最令人兴奋且最复杂的前沿领域之一。研究人员不仅致力于开发能够像人类一样行走和行动的机器人&#xff0c;还致力于开发能够…

C语言高级编程:一文读懂数据结构的四大逻辑与两大存储

各类资料学习下载合集 ​​https://pan.quark.cn/s/8c91ccb5a474​ 作为一名程序员,我们每天都在与“数据”打交道。但你是否想过,这些数据在计算机中是如何被“整理”和“安放”的?为什么有些操作快如闪电,而有些则慢如蜗牛? 答案就藏在数据结构之中。 如果说算法是…

MySQL问题4

MySQL中varchar和char的区别 在 MySQL 中&#xff0c;VARCHAR 和 CHAR 都是用于存储字符串类型的字段&#xff0c;但它们在存储方式、性能、适用场景等方面存在明显区别&#xff1a;1. 存储方式类型说明CHAR(n)定长字符串&#xff0c;始终占用固定 n 个字符空间。不足的会自动在…

Web3 出海香港 101 |BuildSpace AMA 第一期活动高亮观点回顾

香港政府在 2022-2023 年之间已经开始布局 Web3&#xff0c;由香港政府全资拥有的数码港也进行了持续两年多的深耕。目前数码港已有接近 300 家企业入驻于此&#xff0c;包括 Animoca Brands、HashKey Group、CertiK 等行业知名独角兽公司。此外&#xff0c;如 Cobo、OneKey、D…

LTE CA和NR CA的区别和联系

LTE CA&#xff08;Carrier Aggregation&#xff09;和NR CA&#xff08;New Radio Carrier Aggregation&#xff09;都是载波聚合技术&#xff0c;它们的核心目标都是通过组合多个频段的带宽来提高数据传输速率&#xff0c;增强无线网络的吞吐量。尽管它们的功能相似&#xff…

VBA 中的 Excel 工作表函数

一、引言 在使用VBA进行Excel自动化处理时&#xff0c;我们经常需要调用Excel内置的工作表函数来完成复杂的计算或数据处理任务。然而&#xff0c;很多VBA初学者并不清楚如何正确地在VBA中调用这些函数&#xff0c;甚至重复造轮子。本文将从基础到进阶&#xff0c;系统介绍如何…

老年公寓管理系统设计与实现(代码+数据库+LW)

摘要 随着老龄化社会的不断发展&#xff0c;老年人群体的生活质量和管理需求逐渐引起社会的广泛关注。为了提高老年公寓的管理效率与服务质量&#xff0c;开发了一种基于SpringBoot框架的老年公寓管理系统。该系统充分利用了SpringBoot框架的快速开发优势&#xff0c;结合现代…

绿算技术与清智图灵签署战略合作协议

近日&#xff0c;广东省绿算技术有限公司&#xff08;以下简称“绿算技术”&#xff09;与北京清智图灵科技有限公司&#xff08;以下简称“清智图灵”&#xff09;正式签署战略合作框架协议。双方将围绕通用并行计算、高端算力解决方案等领域展开深度合作&#xff0c;共同推动…