☰
v0.2.0 架构升级:class + reactive 重塑状态管理
2026/11/2 1:59:36 网站建设 项目流程

v0.2.0 为重大架构升级:store 定义改为 class + reactive(class XxxStore extends PiniaStoreBase),state 用reactive<T>强类型包裹、派生值用 class getter、action 为普通 method——由此换来完整实例 API($patch/$reset/$subscribe/$onAction/$dispose/$id/$state/$save)与内置持久化插件(createPersistPlugin:store 创建自动恢复、$patch/$reset/$save自动落盘)。⚠️ 破坏性变更:0.1.0 setup 式 API(storeToRefs/ 顶层patch/loadPersisted等)已移除,迁移对照见第四节。

一、为什么升级架构

v0.1.0 的 setup 式 + Ref 形态跑通了下限,但也撞上了天花板——两条平台硬约束:

  • UTS 无 Proxy、无反射:store 对象不可动态挂方法、不可运行时枚举字段,$patch/$subscribe/$onAction/$reset在 setup 式形态下全部无法实现(v0.1.0 只能裁掉)
  • 新版 HBuilderX 编译器对 UTS 插件内运行时类 vue 符号(Ref/watch/effectScope)的 Kotlin import 生成失效——云打包 Kotlin 编译直接 Unresolved

而reactive<T>在 UTS 中是编译期展开(生成属性代理类,getter/setter 内联依赖追踪),不受上述约束影响。class + reactive 因此成为 uni-app x 插件实现完整 Pinia 功能面的唯一可行架构。v0.2.0 完成架构转向,一次补齐:

能力v0.1.0v0.2.0
$patch/$reset顶层patch(mutator)/ ❌✅$patch(partial)/$reset()(_doReset钩子)
$subscribe/$onAction❌(字段级watch替代)✅ 内置(快照分发 /callAction追踪)
$id/$state/$dispose顶层函数映射✅ 实例属性 / 方法
$save显式保存点—✅
持久化❌✅ 内置插件,零胶水

二、核心能力

class 式 defineStore

import { reactive } from 'vue' import { defineStore, PiniaStoreBase } from '@/uni_modules/ux-pinia' export type CounterState = { count: number name: string } export class CounterStore extends PiniaStoreBase { // state:reactive<T> 强类型包裹(字段为原始值,模板 / 脚本直接访问) state: CounterState = reactive<CounterState>({ count: 0, name: 'pinia' }) // 派生值:class getter(每次求值,模板经 reactive 属性依赖收集自动更新) get doubleCount(): number { return this.state.count * 2 } // constructor:super() 后必须 bindState(this.state)($-API 与持久化的前提) constructor() { super() this.bindState(this.state) } // actions = 普通 class method,直接修改 state increment(): void { this.state.count++ } } export const useCounterStore = defineStore<CounterStore>('counter', (): CounterStore => new CounterStore())

结构对齐 Pinia 官方state / getters / actions心智;模板事件绑定 class method 必须带括号(@click="counter.increment()",Kotlin 端 method 不是值)。

完整实例 API($-methods)

const counter = useCounterStore() counter.$patch({ count: 10 } as UTSJSONObject) // 批量修改(经 _hydrate 钩子装载) counter.$reset() // 重置(_doReset 钩子) const unsub = counter.$subscribe((type: string, state: UTSJSONObject): void => { // type = 'patch' | 'reset' | 'save';state = _serialize() 快照 }) counter.$onAction((info: ActionInfo): void => { /* action 追踪 */ }) counter.$save() // 显式保存点(direct 修改 state 后的落盘触发) counter.$dispose() // 注销,下次 useStore() 重建 counter.$id // 'counter'

$subscribe仅由$patch/$reset/$save触发(UTS 无全局订阅钩子);direct 修改 state 后的关键操作请调用counter.$save()。

内置持久化插件(零胶水)

main.uts顶层登记一次,全部 store 生效:

import { createPinia, setActivePinia, createPersistPlugin } from '@/uni_modules/ux-pinia' setActivePinia(createPinia().use(createPersistPlugin({ keyPrefix: 'ux-pinia:', includeStores: null, // null = 全部 store excludeStores: new Array<string>(), serializer: null // null = JSON 序列化 })))

需要持久化的 store 重写两个钩子(Template Method 契约):

override _serialize(): UTSJSONObject { // 落盘快照:只含需持久化的字段 return { token: this.state.token } as UTSJSONObject } override _hydrate(data: UTSJSONObject): void { // 恢复回填:字段级判空(存储损坏 / 字段缺失 → 保留初始值) if (data['token'] != null) { this.state.token = data['token'] as string } }

恢复在 store 创建时自动发生;落盘由$patch/$reset/$save自动触发。对比旧版「每字段两行 ref / watch 胶水」的方案,持久化成本降为两个声明式钩子。存储后端可经setStorageAdapter替换(默认 uni storage,可换 unix-storage / 原生 preferences);clearPersistedState(storeId, keyPrefix)可清空单个 store。

免挂载单例与插件体系(一如既往)

模块级注册表保证应用级单例,跨页面共享状态,无需app.use(实测原生端app.use不触发 install,免挂载是唯一双端一致的形态);插件pinia.use(plugin)链式注册,PiniaPluginContext(pinia/store/storeId)对齐标准 Pinia——持久化插件本身就是插件体系的第一个内置成员。

三、平台支持现状

平台状态
Web✅ 全用例通过(基础用法 / 响应式 / 单例跨页面 / 实例 API / 跨 store / 订阅 / 插件 / 持久化)
Android✅ 蒸汽模式(vapor)云打包 Kotlin 编译链通过,真机用例复验中
iOS / 鸿蒙⏳ 代码全端同构(纯 UTS、无平台分支),待实测

关键实测裁决(驱动本次架构定稿):reactive<T>为编译期展开(Kotlin 生成正常);运行时类 vue 符号(Ref/ref/watch/effectScope)在插件内 Kotlin import 生成失效(effectScope被生成器静默丢弃——派生值因此用 getter 而非 computed);模板 class method 绑定必须带括号;Kotlin 泛型擦除边界(error17)在库内收敛,业务侧零感知。

四、0.1.0 → 0.2.0 迁移对照

v0.1.0(setup 式,已移除)v0.2.0(class 式)
type CounterStore = { count: Ref<number>, ... }+ setup 函数class CounterStore extends PiniaStoreBase(state =reactive<T>字段)
脚本store.count.value/ 模板storeToRefs解构store.state.count直接读写,脚本模板同路径
patch(store, fn)store.$patch(partial)或直接调用 action
字段级watch(store.count, cb)store.$subscribe(cb)
自定义 reset actionstore.$reset()(_doReset钩子)
loadPersisted/savePersisted+ 每字段 ref / watch 胶水createPersistPlugin+_serialize/_hydrate双钩子
getStoreId(store)/dispose(store)store.$id/store.$dispose()(顶层函数仍保留)

五、快速上手

pnpmadd@meng-xi/unix-piniamkdir-puni_modules&&cp-Rnode_modules/@meng-xi/unix-pinia uni_modules/ux-pinia

插件市场搜索ux-pinia导入亦可。定义 store 见第二节 class 式示例;页面直接消费counter.state.count与 getter。不想搭工程?安卓真机可直接下载体验 App:下载体验 App(APK)——示例工程云打包产物(蒸汽模式),安装后进入各功能页即可在真机运行全部用例。

六、文档与资源

  • 📖 完整文档(指南 9 篇 + API 3 篇,中英双语,从入门到精通)
  • 📝 更新日志

相关链接

  • 示例工程 packages/playground(首页分组导航 + 9 个功能验证页,HBuilderX 发行 Web / 云打包验证)
  • API 参考

欢迎反馈与共建:GitHub

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询