Pinia状态管理库提供Options和Setup两种Store写法。Options Store采用对象配置式包含state、getters和actions三个选项适合简单场景和Vue2开发者Setup Store使用函数组合式通过ref/computed定义状态和计算属性天然支持TS类型推导适合复杂逻辑和复用需求。两种方式功能等价但风格迥异Options按类型分组Setup按功能组织。实际使用中模板调用方式完全一致开发者可根据项目复杂度、技术偏好选择甚至混合使用。个人推荐使用 option 方式以获取最大功能支持。官网https://pinia.vuejs.org/zh/core-concepts/Pinia Store 的两种书写方式对比官网解释Store 是用defineStore()定义的它的第一个参数要求是一个独一无二的名字。这个名字也被用作id是必须传入的 Pinia 将用它来连接 store 和 devtools。为了养成习惯性的用法将返回的函数命名为use...是一个符合组合式函数风格的约定。defineStore()的第二个参数可接受两类值Setup 函数或 Option 对象。1. Options Store选项式// stores/counter.js import { defineStore } from pinia export const useCounterStore defineStore(counter, { // state数据源 state: () ({ count: 0, name: Counter }), // getters计算属性 getters: { doubleCount: (state) state.count * 2, // 使用 this 访问其他 getter doubleCountPlusOne() { return this.doubleCount 1 } }, // actions方法支持异步 actions: { increment() { this.count }, async fetchData() { // 异步操作 const data await api.getData() this.name data.name } } })2. Setup Store组合式// stores/counter.js import { defineStore } from pinia import { ref, computed } from vue export const useCounterStore defineStore(counter, () { // state使用 ref/reactive const count ref(0) const name ref(Counter) // getters使用 computed const doubleCount computed(() count.value * 2) const doubleCountPlusOne computed(() doubleCount.value 1) // actions普通函数 function increment() { count.value } async function fetchData() { const data await api.getData() name.value data.name } // 必须返回所有要暴露的状态和方法 return { count, name, doubleCount, doubleCountPlusOne, increment, fetchData } })3. 核心对比特性Options StoreSetup Store语法风格对象配置式函数组合式响应式数据state对象ref()/reactive()计算属性getters对象computed()方法actions对象普通函数this 指向指向 store 实例无 this或需注意TypeScript需额外类型声明天然类型推导代码组织按类型分组按功能组织复用逻辑Mixins不推荐Composables推荐4. 使用示例template div pCount: {{ counter.count }}/p pDouble: {{ counter.doubleCount }}/p button clickcounter.increment增加/button /div /template script setup import { useCounterStore } from /stores/counter const counter useCounterStore() // 两种方式使用方式完全一致 /script5. 选择建议Options Store 更适合简单、标准的数据存储熟悉 Vue 2 Options API 的开发者需要快速上手的项目Setup Store 更适合复杂的业务逻辑需要高度复用的逻辑充分利用 Composition API 的项目需要更好的 TypeScript 支持6. 混合使用// 你甚至可以在 Setup Store 中使用 Options 的语法 export const useStore defineStore(store, () { // setup 语法 const count ref(0) // 仍然可以使用 $state、$onAction 等 Store 实例方法 return { count } })两种方式在功能上完全等价选择哪种主要取决于个人偏好和项目需求。方法Setup Store 没有$patch方法$patch是 Pinia store 实例的内置方法不管使用 Options 还是 Setup 方式创建的 store都有这个方法。// 查看 store 实例的所有方法 console.log(Object.keys(store)) // [$id, $patch, $reset, $subscribe, $onAction, ...]但是在 Setup Store 中没有this指向 store 实例所有状态和方法都是通过闭包变量直接访问$patch是 store 实例的方法不是 setup 函数内部的方法总结修改方式适用场景优点缺点直接修改 ref.value大多数情况简单直观TypeScript 友好多次修改触发多次更新store.$patch()批量更新一次更新性能好需要获取 store 实例辅助函数复杂 store封装性好可复用增加代码量推荐做法简单的赋值操作直接修改.value需要批量更新使用$patch但要正确获取 store 实例避免在 Setup Store 中使用thisSetup Store 的 $reset 方法需要注意的是Setup Store默认没有$reset方法需要手动实现// Options Store - 自动有 $reset const optionsStore useOptionsStore() optionsStore.$reset() // ✅ 直接可用 // Setup Store - 需要手动实现 export const useSetupStore defineStore(counter, () { const count ref(0) const name ref(Counter) // 保存初始状态 const initialState { count: 0, name: Counter } function increment() { count.value } // 手动实现 reset 方法 function $reset() { count.value initialState.count name.value initialState.name } return { count, name, increment, $reset // 手动返回 reset 方法 } })批量修改状态的几种方式对比const store useCounterStore() // 1. 多次单独修改触发多次更新 store.count store.name New store.items.push(item) // 2. 使用 $patch 对象形式一次更新 store.$patch({ count: store.count 1, name: New // items 不能直接 push需要新数组 }) // 3. 使用 $patch 函数形式一次更新更灵活 store.$patch((state) { state.count state.name New state.items.push(item) // 可以执行复杂操作 }) // 4. 组合式 API 风格Setup Store 特有 function batchUpdate() { // 虽然看起来是多次修改但 Vue 会自动批量更新 store.count store.name New store.items.push(item) }总结✅$patch 方法在两种 Store 中都存在是 Pinia 实例的内置方法✅ 两种方式使用 $patch 的语法完全相同⚠️ 只有$reset方法在 Setup Store 中需要手动实现 $patch 的主要优势是批量更新和部分更新减少不必要的重新渲染
Pinia Store 的两种书写(option 和 setup)方式对比
Pinia状态管理库提供Options和Setup两种Store写法。Options Store采用对象配置式包含state、getters和actions三个选项适合简单场景和Vue2开发者Setup Store使用函数组合式通过ref/computed定义状态和计算属性天然支持TS类型推导适合复杂逻辑和复用需求。两种方式功能等价但风格迥异Options按类型分组Setup按功能组织。实际使用中模板调用方式完全一致开发者可根据项目复杂度、技术偏好选择甚至混合使用。个人推荐使用 option 方式以获取最大功能支持。官网https://pinia.vuejs.org/zh/core-concepts/Pinia Store 的两种书写方式对比官网解释Store 是用defineStore()定义的它的第一个参数要求是一个独一无二的名字。这个名字也被用作id是必须传入的 Pinia 将用它来连接 store 和 devtools。为了养成习惯性的用法将返回的函数命名为use...是一个符合组合式函数风格的约定。defineStore()的第二个参数可接受两类值Setup 函数或 Option 对象。1. Options Store选项式// stores/counter.js import { defineStore } from pinia export const useCounterStore defineStore(counter, { // state数据源 state: () ({ count: 0, name: Counter }), // getters计算属性 getters: { doubleCount: (state) state.count * 2, // 使用 this 访问其他 getter doubleCountPlusOne() { return this.doubleCount 1 } }, // actions方法支持异步 actions: { increment() { this.count }, async fetchData() { // 异步操作 const data await api.getData() this.name data.name } } })2. Setup Store组合式// stores/counter.js import { defineStore } from pinia import { ref, computed } from vue export const useCounterStore defineStore(counter, () { // state使用 ref/reactive const count ref(0) const name ref(Counter) // getters使用 computed const doubleCount computed(() count.value * 2) const doubleCountPlusOne computed(() doubleCount.value 1) // actions普通函数 function increment() { count.value } async function fetchData() { const data await api.getData() name.value data.name } // 必须返回所有要暴露的状态和方法 return { count, name, doubleCount, doubleCountPlusOne, increment, fetchData } })3. 核心对比特性Options StoreSetup Store语法风格对象配置式函数组合式响应式数据state对象ref()/reactive()计算属性getters对象computed()方法actions对象普通函数this 指向指向 store 实例无 this或需注意TypeScript需额外类型声明天然类型推导代码组织按类型分组按功能组织复用逻辑Mixins不推荐Composables推荐4. 使用示例template div pCount: {{ counter.count }}/p pDouble: {{ counter.doubleCount }}/p button clickcounter.increment增加/button /div /template script setup import { useCounterStore } from /stores/counter const counter useCounterStore() // 两种方式使用方式完全一致 /script5. 选择建议Options Store 更适合简单、标准的数据存储熟悉 Vue 2 Options API 的开发者需要快速上手的项目Setup Store 更适合复杂的业务逻辑需要高度复用的逻辑充分利用 Composition API 的项目需要更好的 TypeScript 支持6. 混合使用// 你甚至可以在 Setup Store 中使用 Options 的语法 export const useStore defineStore(store, () { // setup 语法 const count ref(0) // 仍然可以使用 $state、$onAction 等 Store 实例方法 return { count } })两种方式在功能上完全等价选择哪种主要取决于个人偏好和项目需求。方法Setup Store 没有$patch方法$patch是 Pinia store 实例的内置方法不管使用 Options 还是 Setup 方式创建的 store都有这个方法。// 查看 store 实例的所有方法 console.log(Object.keys(store)) // [$id, $patch, $reset, $subscribe, $onAction, ...]但是在 Setup Store 中没有this指向 store 实例所有状态和方法都是通过闭包变量直接访问$patch是 store 实例的方法不是 setup 函数内部的方法总结修改方式适用场景优点缺点直接修改 ref.value大多数情况简单直观TypeScript 友好多次修改触发多次更新store.$patch()批量更新一次更新性能好需要获取 store 实例辅助函数复杂 store封装性好可复用增加代码量推荐做法简单的赋值操作直接修改.value需要批量更新使用$patch但要正确获取 store 实例避免在 Setup Store 中使用thisSetup Store 的 $reset 方法需要注意的是Setup Store默认没有$reset方法需要手动实现// Options Store - 自动有 $reset const optionsStore useOptionsStore() optionsStore.$reset() // ✅ 直接可用 // Setup Store - 需要手动实现 export const useSetupStore defineStore(counter, () { const count ref(0) const name ref(Counter) // 保存初始状态 const initialState { count: 0, name: Counter } function increment() { count.value } // 手动实现 reset 方法 function $reset() { count.value initialState.count name.value initialState.name } return { count, name, increment, $reset // 手动返回 reset 方法 } })批量修改状态的几种方式对比const store useCounterStore() // 1. 多次单独修改触发多次更新 store.count store.name New store.items.push(item) // 2. 使用 $patch 对象形式一次更新 store.$patch({ count: store.count 1, name: New // items 不能直接 push需要新数组 }) // 3. 使用 $patch 函数形式一次更新更灵活 store.$patch((state) { state.count state.name New state.items.push(item) // 可以执行复杂操作 }) // 4. 组合式 API 风格Setup Store 特有 function batchUpdate() { // 虽然看起来是多次修改但 Vue 会自动批量更新 store.count store.name New store.items.push(item) }总结✅$patch 方法在两种 Store 中都存在是 Pinia 实例的内置方法✅ 两种方式使用 $patch 的语法完全相同⚠️ 只有$reset方法在 Setup Store 中需要手动实现 $patch 的主要优势是批量更新和部分更新减少不必要的重新渲染