v0.1.0 为首个公开版本 :以 uni-app x 内建响应式原语(
ref/computed/reactive/watch)为唯一底层依赖、不重造响应式栈,把 store 组织、跨页面单例、实例 API 这些标准 Pinia 在 vdom 模式 App 原生端给不了的能力收进一套 Pinia 心智的 API。Web 与 Android 真机全用例通过,云打包 release 编译零错误。
一、为什么做这个库
uni-app x 的 vdom 模式 App 原生端,标准 Pinia 因 UTS 强类型约束(Proxy、动态属性、Partial<T> 缺失)无法编译;官方仅推荐"导出模块级 reactive 变量"的裸方案。直接用它写业务,四件事反复发生:
- 无统一范式:state、派生值、修改逻辑混在一个 reactive 对象里,命名与组织全靠自觉,项目一大就失控
- 无单例保证:跨页面共享同一份可变全局,"谁在什么时候创建了什么"全靠约定,同 id 冲突静默覆盖
- 无实例 API:批量更新、清理重建、反查归属都要业务手写,每个项目重复一遍
- 迁移成本:将来项目切到蒸汽模式(标准 Pinia 全平台可用),调用方代码要全部重写
unix-pinia 把这些收敛成一套库:写过 Pinia 的开发者看一眼 API 就能上手(defineStore / storeToRefs / createPinia);单例由模块级注册表保证;实例 API 一比一对齐;每个裁掉项都有明确原因与替代方案------将来迁移回标准 Pinia,业务调用方代码几乎零改动。
二、核心能力
setup 式 defineStore
uts
import type { Ref, ComputedRef } from 'vue'
import { defineStore } from '@/uni_modules/ux-pinia'
export type CounterStore = {
count: Ref<number>, // state:Ref
doubleCount: ComputedRef<number>, // getter:ComputedRef
increment: () => void // action:箭头函数
}
export const useCounterStore = defineStore<CounterStore>('counter', (): CounterStore => {
const count: Ref<number> = ref(0)
const doubleCount: ComputedRef<number> = computed((): number => count.value * 2)
const increment = (): void => { count.value++ }
return { count, doubleCount, increment } as CounterStore
})
state 用 Ref、getter 用 ComputedRef、action 用箭头函数,与 Pinia 官方推荐的 setup store 写法一致;返回类型显式 type 标注,编辑器全程提示。
免挂载单例,跨页面共享
模块级注册表保证应用级单例:同 id 多次 useStore 返回同一实例,跨页面共享状态,无需 app.use (实测原生端 app.use 不触发 install,免挂载是唯一双端一致的形态);同 id 重复 defineStore 警告并保持幂等。
实例 API 顶层函数映射
uts
import { patch, dispose, getStoreId } from '@/uni_modules/ux-pinia'
patch(store, (s: CounterStore): void => { s.count.value = 10 }) // ≙ store.$patch(fn)
const id: string = getStoreId(store) // ≙ store.$id
dispose(store) // ≙ store.$dispose()
UTS 无 Proxy、对象不可动态注入属性,$patch / $id / $dispose 以顶层函数形态一比一映射,语义不变。
跨 store 与插件体系
uts
// 跨 store 依赖:setup 内直接调用对方 useStore,注册表保证单例
const counterStore = useCounterStore()
// 插件:pinia.use 链式注册,PiniaPluginContext(pinia / store / storeId)对齐标准 Pinia
setActivePinia(createPinia().use(myPlugin))
一比一复刻,裁掉有据
设计原则对标 unix-router 复刻 vue-router:Pinia 的每个公开 API 都给出"直接实现 / 裁掉(附原因与替代)"的归属。裁掉项(Options 式、$subscribe、$onAction、$state、$patch 对象形态等)全部源于 UTS 平台硬约束并经双端实测裁决,详见差异对照。
三、平台支持现状
| 平台 | 状态 |
|---|---|
| Web | ✅ 全用例通过(9 个功能页:基础用法 / 响应式矩阵 / 单例幂等 / 实例 API / 跨 store / 订阅 / 插件 / 跨页面) |
| Android | ✅ Kotlin 编译链真机全用例通过;云打包 release 编译零错误 |
| iOS / 鸿蒙 | ⏳ 代码全端同构(纯 UTS、无平台分支),待实测 |
关键双端实测裁决:reactive() 对 Ref 字段 Web 解包 / Android 保持 RefImpl(据采用透传形态,不依赖解包);deep watch 对 RefImpl 字段 Android 不触发($subscribe 据此裁掉,字段级 watch 替代);Kotlin 泛型擦除边界(error17)在库内收敛,业务侧零感知。
四、快速上手
bash
pnpm add @meng-xi/unix-pinia
mkdir -p uni_modules && cp -R node_modules/@meng-xi/unix-pinia uni_modules/ux-pinia
vue
<script setup lang="uts">
import { storeToRefs } from '@/uni_modules/ux-pinia'
import { useCounterStore } from '@/stores/counter.uts'
const store = useCounterStore()
const { count, doubleCount } = storeToRefs(store) // 模板解构自动解包
</script>
<template>
<text>{{ count }} / {{ doubleCount }}</text>
</template>
不想搭工程?安卓真机可直接下载体验 App :下载体验 App(APK)------示例工程的云打包产物(vdom 模式),安装后进入各功能页即可在真机运行全部用例。
五、文档与资源
相关链接
- 示例工程 packages/playground(首页分组导航 + 9 个功能验证页,HBuilderX 发行 Web / 云打包验证)
- API 参考
欢迎反馈与共建:GitHub