uni-app x 专属 Pinia 库正式发布

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 模式),安装后进入各功能页即可在真机运行全部用例。

五、文档与资源

相关链接

欢迎反馈与共建:GitHub

相关推荐
一次旅行2 小时前
DeepSeek‑V4.1‑Flash‑1017完整解读:模型升级+Search/Fetch搜索API开放,Agent开发者要注意哪些坑
前端·网络·人工智能
原则猫11 小时前
UDP 到底怎么实现可靠的
前端
Java后端的Ai之路11 小时前
14、ReactJS - 路由(Router)
前端·react.js·状态模式
裕晟资质规划12 小时前
三类涉密资质延续时限差异分析:军工60日与集成印制3个月的边界
java·服务器·前端·网络·安全
ShineWinsu12 小时前
对于JavaScript:JavaScript基础语法的解析
开发语言·前端·javascript·面试·web·基础语法·循环
月夏12 小时前
Vue3 转 React:18 项对照表 + 5 个必踩的坑(附 7 天上手路线)
前端
广州华水科技12 小时前
单北斗GNSS位移监测系统的应用与维护解析
前端
梦曦i13 小时前
uni-storage 0.1.0 发布:TTL过期管理+多实例隔离
前端·storage·uni-app x
猫头_14 小时前
AI 流式传输工程指南:模型吐出半截 JSON,前端如何边收边渲染?
前端·javascript·llm