Store(状态管理)
wevu 内置了类 Pinia 的 Store,直接从 wevu 主入口导入,无需全局注册,也不支持 wevu/store 这样的子路径。
导入与核心 API
defineStore(id, setup | options):定义 Store,返回useXxx()获取单例实例。storeToRefs(store):将 state/getter 包装为ref,函数保持原样,解构不丢失响应式。createStore():可选的插件入口;只有需要插件时才调用(见下文)。
Setup Store 示例(推荐)
ts
// stores/counter.ts
import { computed, defineStore, ref } from 'wevu'
export const useCounter = defineStore('counter', () => {
const count = ref(0)
const doubled = computed(() => count.value * 2)
const inc = () => count.value++
return { count, doubled, inc }
})Options Store 示例
ts
// stores/user.ts
import { defineStore } from 'wevu'
export const useUser = defineStore('user', {
state: () => ({ name: '', age: 0 }),
getters: {
label(state) {
return `${state.name}:${state.age}`
},
canVote() {
return this.age >= 18
},
},
actions: {
grow() {
this.age += 1
},
},
})在页面/组件中使用
ts
// pages/counter/index.ts
import { definePage, storeToRefs } from 'wevu'
import { useCounter } from '@/stores/counter'
export default definePage({
setup() {
const counter = useCounter()
const { count, doubled } = storeToRefs(counter)
counter.$subscribe((mutation) => {
console.log('[counter]', mutation.type, mutation.storeId)
})
return { count, doubled, inc: counter.inc }
},
})要点:
- Store 是单例,在页面/组件
setup里调用useXxx()即可复用。 - 解构 state/getter 请使用
storeToRefs,actions 可以直接解构。
插件与订阅
- 默认无需插件即可使用;只有当你需要统一扩展所有 Store 时再调用
createStore()并注册插件。 - 插件需在第一次
useXxx()之前注册。createStore()内部会被记录为全局单例,defineStore会自动读取并应用插件。
ts
import { createStore, defineStore } from 'wevu'
const manager = createStore()
manager.use(({ store }) => {
store.$onAction((ctx) => {
ctx.after(res => console.log('[after]', ctx.name, res))
ctx.onError(err => console.error('[error]', ctx.name, err))
})
store.$subscribe((mutation, state) => {
console.log(`[${store.$id}]`, mutation.type, state)
})
})
// 之后定义的任何 store 都会自动套用上述插件
export const useCart = defineStore('cart', {
state: () => ({ items: [] as Array<{ id: string, count: number }> }),
actions: {
add(id: string, count = 1) {
const found = this.items.find(i => i.id === id)
if (found) {
found.count += count
}
else { this.items.push({ id, count }) }
},
},
})Store 实例 API
$id:当前 Store 的唯一标识。$state(Options Store):读取/替换整个 state;赋值会做浅合并并触发patch object。$patch(patch | fn):批量修改;Setup/Options Store 均可用,支持对象合并或回调方式。$reset()(Options Store):将 state 重置为初始值。$subscribe((mutation, state) => void):订阅 state 变化,返回取消订阅函数;mutation.type可能是patch object或patch function。$onAction(({ name, store, args, after, onError }) => void):订阅 action 调用,支持成功/失败回调。storeToRefs(store):将所有非函数字段转换为可写ref,函数保持原样,避免解构丢失响应式。
TypeScript 与最佳实践
- Setup Store 会自动推导返回对象的类型;Options Store 可通过泛型精确声明
state/getters/actions。 - Store 文件按功能域组织(例如
stores/user.ts、stores/cart.ts),Store ID 使用小写单数。 - 避免直接解构 state:使用
storeToRefs;actions 可以直接解构。 - SSR/HMR/Devtools:wevu 面向小程序运行环境,暂未提供这些 Web 专属能力。
常见问题
- 不要从
wevu/store导入,所有 API 均在wevu主入口。 - 不需要为了使用 store 先调用
createStore();仅在使用插件时才需要。