Pinia 的 defineStore 函数式写法是官方推荐的主流方式,用纯函数定义 store,结构清晰、类型推导友好、逻辑复用方便;它以字符串 ID 和返回响应式数据的函数为参数,支持 ref/computed/组合式 API,无需 this,自动响应,按需初始化。

Pinia 的 defineStore 函数式写法是官方推荐的主流方式,它用纯函数定义 store,结构清晰、类型推导友好、逻辑复用方便,比 Options API 更现代简洁。
基础用法:定义一个简单 store
在 src/stores/counter.ts(或 .js)中:
import { defineStore } from 'pinia'
<p>export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)</p><p>function increment() {
count.value++
}
function reset() {
count.value = 0
}</p><p>return {
count,
doubleCount,
increment,
reset
}
})
✅ 关键点:
- 第一个参数是 store 的唯一 ID(用于调试和 SSR),必须是字符串
- 第二个参数是一个函数,返回所有响应式状态、计算属性和方法
- 内部可直接使用 ref、computed、onMounted 等组合式 API
如何在组件中使用这个 store
在 Vue 单文件组件中:
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
<p>const counter = useCounterStore()
</script></p><p><template>
<div>
<p>计数:{{ counter.count }}</p>
<p>两倍:{{ counter.doubleCount }}</p>
<button @click="counter.increment">+1</button>
<button @click="counter.reset">重置</button>
</div>
</template>
⚠️ 注意:
- 不需要手动调用 counter(),useCounterStore 已是可执行函数,调用即获取 store 实例
- 所有返回的属性自动具备响应性,无需额外解构或 storeToRefs(除非需避免副作用)
进阶:支持选项式写法兼容与 TypeScript 类型
如果需要明确类型提示或兼容部分旧习惯,也可用对象形式传参(但仍是函数式风格):
立即学习“前端免费学习笔记(深入)”;
export const useUserStore = defineStore('user', {
state: () => ({
name: ref<string>(''),
age: ref<number>(0),
isLogin: ref<boolean>(false)
}),
getters: {
fullName(): string {
return this.name + '(' + this.age + '岁)'
}
},
actions: {
login(name: string, age: number) {
this.name = name
this.age = age
this.isLogin = true
}
}
})
? 提示:
- 这种写法本质仍是组合式 API 底层,state/getters/actions 会被自动转换为响应式逻辑
- this 指向当前 store 实例,类型由 Pinia 自动推导,TypeScript 支持完善
- 推荐优先使用纯函数式(第一种),更灵活、无 this 陷阱、便于单元测试
常见注意事项
使用 defineStore 函数式写法时要注意:
- store 文件默认不自动执行,只在首次调用
useXXXStore()时初始化,适合按需加载 - 不要在 store 函数内直接访问
this—— 函数式写法没有 this 绑定,所有数据都通过返回值暴露 - 如需跨 store 调用,可在函数体内导入其他 store 并直接使用:
const other = useOtherStore() - 若 store 中用了
onMounted等生命周期钩子,它们只在 store 被组件首次使用且该组件挂载时触发(非全局)

















