更新记录

0.0.1(2026-04-22) 下载此版本

新增功能

  • class-based PiniaStore 基类实现

    • 使用 reactive 定义 state
    • bindState() 绑定响应式状态
    • 完整的 $id 和 $state 支持
  • 核心 API 实现

    • $patch() - 批量修改状态(对象/函数方式)
    • $reset() - 重置到初始状态
    • $subscribe() - 订阅状态变化
    • $onAction() - 订阅动作执行
    • $action() - 包装方法以支持订阅
  • 持久化插件

    • uni.setStorageSync 自动保存
    • 支持 keyPrefix 配置
    • 支持 includeStores / excludeStores 过滤
    • 支持自定义序列化
    • clearPersistedState() 手动清除
  • 插件机制

    • createPinia() 创建根实例
    • use() 注册插件
    • 插件上下文支持 storeId、pinia、store 等
  • 模块化架构

    • types.uts - 类型定义
    • createPinia.uts - Pinia 根实例创建
    • store.uts - PiniaStore 基类
    • persist.uts - 持久化插件
    • index.uts - 统一导出

文档


平台兼容性

uni-app x(5.03)

Chrome Safari Android iOS 鸿蒙 微信小程序

lime-pinia

Pinia 状态管理库,专为 uni-app-x 设计,使用 UTS 实现的 class-based 版本

快速开始

安装

在 uni-app 插件市场中搜索并导入 lime-pinia

基础使用步骤

  1. 在 main.uts 中初始化 Pinia
  2. 定义你自己的 Store
  3. 在页面或组件中使用

1. 初始化 Pinia

在你的项目入口 main.uts 中:

import { createSSRApp } from 'vue'
import App from './App.uvue'
import { createPinia, createPersistPlugin } from '@/uni_modules/lime-pinia'

export function createApp() {
    const app = createSSRApp(App)
    const pinia = createPinia()

    // (可选)开启持久化
    pinia.use(createPersistPlugin())

    app.use(pinia)
    return {
        app
    }
}

2. 定义你的 Store

继承 PiniaStore 类即可。

**必须做的两件事:

  • ✅ 使用 reactive() 定义 state
  • ✅ 在构造函数中调用 this.bindState(state)

示例:

import { defineStore, PiniaStore } from '@/uni_modules/lime-pinia'
import { reactive } from 'vue'

// 第一步:定义你的 State 类型
export type UserState = {
    name : string
    age : number
    theme : 'light' | 'dark'
}

// 第二步:继承 PiniaStore
export class UserStore extends PiniaStore<UserState> {
    // 【必须】用 reactive 创建响应式状态
    state = reactive<UserState>({
        name: '张三',
        age: 25,
        theme: 'light'
    })

    constructor() {
        super()
        // 【必须】绑定 state
        this.bindState(this.state)
    }

    // 定义业务方法(建议用 $action 包装)
    setName(name: string) {
        this.$action('setName', () => {
            this.state.name = name
        }, [name])
    }

    setAge(age: number) {
        this.$action('setAge', () => {
            this.state.age = age
        }, [age])
    }

    toggleTheme() {
        this.$action('toggleTheme', () => {
            this.state.theme = this.state.theme == 'light' ? 'dark' : 'light'
        })
    }
}

// 第三步:创建 use 函数
export const useUserStore = defineStore<UserState, UserStore>('user', new UserStore())

3. 在页面中使用

<view class="container">
    <text>姓名: {{ user.state.name }}</text>
    <text>年龄: {{ user.state.age }}</text>
    <text>主题: {{ user.state.theme }}</text>

    <input v-model="nameInput" placeholder="输入姓名" />
    <button @click="updateName">更新姓名</button>

    <input v-model="ageInput" placeholder="输入年龄" />
    <button @click="updateAge">更新年龄</button>

    <button @click="toggleTheme">切换主题</button>
    <button @click="resetStore">重置</button>
</view>
import { ref } from 'vue'
import { useUserStore } from '@/stores/user'

const user = useUserStore()
const nameInput = ref('')
const ageInput = ref('')

function updateName() {
    if (nameInput.value != '') {
        user.setName(nameInput.value)
    }
}

function updateAge() {
    const age = parseInt(ageInput.value)
    if (isNaN(age) != true) {
        user.setAge(age)
    }
}

function toggleTheme() {
    user.toggleTheme()
}

function resetStore() {
    user.$reset()
    nameInput.value = ''
    ageInput.value = ''
}

4. 核心 API 速查

访问数据和状态操作

$patch() - 批量修改

// 对象方式
user.$patch({
    name: '李四',
    age: 30
})

// 函数方式
user.$patch((state) => {
    state.name = '王五'
    state.age = 35
})

$reset() - 重置到初始值

user.$reset()

订阅(监听)

$subscribe() - 监听状态变化

import { onMounted, onUnmounted } from 'vue'
import { useUserStore } from '@/stores/user'

const user = useUserStore()
let unsubscribe = null

onMounted(() => {
    unsubscribe = user.$subscribe((mutation, state) => {
        console.log('变化类型:', mutation.type)
        console.log('最新状态:', state)
    })
})

onUnmounted(() => {
    unsubscribe?.()
})

$onAction() - 监听动作执行

import { onMounted, onUnmounted } from 'vue'
import { useUserStore } from '@/stores/user'

const user = useUserStore()
let unsubscribe = null

onMounted(() => {
    unsubscribe = user.$onAction((ctx, after, onError) => {
        console.log('执行的动作:', ctx.name)

        after((result) => {
            console.log('执行完成:', result)
        })

        onError((error) => {
            console.error('执行出错:', error)
        })
    })
})

onUnmounted(() => {
    unsubscribe?.()
})

4. 持久化插件使用

基本使用

import { createPersistPlugin } from '@/uni_modules/lime-pinia'

const pinia = createPinia()
pinia.use(createPersistPlugin())
app.use(pinia)

自定义配置

pinia.use(createPersistPlugin({
    keyPrefix: 'my-pinia-', // 存储前缀
    includeStores: ['user', 'counter'], // 只持久化这些 store
    excludeStores: [], // 排除这些
    serializer: null // 自定义序列化
}))

手动清除持久化

import { clearPersistedState } from '@/uni_modules/lime-pinia'
clearPersistedState('user') // 清除名为 user 的持久化

6. 关键说明

API 速查表

属性/方法 用途
$id Store 的唯一 ID
$state 获取当前状态
$patch() 批量修改状态
$reset() 重置到初始状态
$subscribe() 订阅状态变化
$onAction() 订阅动作执行
$action() 包装方法以支持订阅
bindState() 绑定响应式 state

重要注意事项

  1. 必须reactive() 定义 state
  2. 继承 PiniaStore 的类,必须在构造函数中调用 this.bindState(state)
  3. 建议用 $action 包装业务方法,这样 $onAction 才能工作
  4. 持久化插件会在 $patch()$reset()$action() 调用时自动保存
  5. 与原始 Pinia 的 Option / Setup Store 不一样,这是 class-based 的实现方式

7. 从原始 Pinia 转换

如果你正在使用原始 Pinia,下面是转换到 lime-pinia 的快速对比:

原始 Pinia (Options Store)

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: '张三',
    age: 25,
    theme: 'light'
  }),

  actions: {
    setName(name: string) {
      this.name = name
    },
    setAge(age: number) {
      this.age = age
    },
    toggleTheme() {
      this.theme = this.theme == 'light' ? 'dark' : 'light'
    }
  }
})

原始 Pinia (Setup Store) - ⚠️ 不支持

原始 Pinia 也支持 setup 风格,但 lime-pinia 不支持,因为我们使用的是 class-based 风格:

import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useUserStore = defineStore('user', () => {
  const name = ref('张三')
  const age = ref(25)
  const theme = ref('light')

  const setName = (nameValue: string) => {
    name.value = nameValue
  }

  const setAge = (ageValue: number) => {
    age.value = ageValue
  }

  const toggleTheme = () => {
    theme.value = theme.value == 'light' ? 'dark' : 'light'
  }

  return {
    name,
    age,
    theme,
    setName,
    setAge,
    toggleTheme
  }
})

⚠️ lime-pinia 不支持 setup store 风格,请使用 class-based 风格

从 Setup Store 转换

如果你正在使用 setup store,下面是如何转换到 lime-pinia:

// 原始 setup store
export const useUserStore = defineStore('user', () => {
  const name = ref('张三')
  const age = ref(25)
  const theme = ref('light')

  const setName = (nameValue: string) => {
    name.value = nameValue
  }
  // ...
})

// 转换为 lime-pinia
class UserStore extends PiniaStore<UserState> {
  state = reactive<UserState>({
    name: '张三',
    age: 25,
    theme: 'light'
  })

  constructor() {
    super()
    this.bindState(this.state)
  }

  // 将 ref 改为 state 访问,.value 去掉
  setName(name: string) {
    this.$action('setName', () => {
      this.state.name = name // 原来是 name.value = name
    }, [name])
  }
  // ...
}

转换为 lime-pinia

import { defineStore, PiniaStore } from '@/uni_modules/lime-pinia'
import { reactive } from 'vue'

// 1. 定义 State 类型
type UserState = {
  name: string
  age: number
  theme: 'light' | 'dark'
}

// 2. 继承 PiniaStore
class UserStore extends PiniaStore<UserState> {
  // 3. 使用 reactive 定义 state
  state = reactive<UserState>({
    name: '张三',
    age: 25,
    theme: 'light'
  })

  constructor() {
    super()
    // 4. 在构造函数中绑定 state
    this.bindState(this.state)
  }

  // 5. 定义业务方法(建议用 $action 包装)
  setName(name: string) {
    this.$action('setName', () => {
      this.state.name = name
    }, [name])
  }

  setAge(age: number) {
    this.$action('setAge', () => {
      this.state.age = age
    }, [age])
  }

  toggleTheme() {
    this.$action('toggleTheme', () => {
      this.state.theme = this.state.theme == 'light' ? 'dark' : 'light'
    })
  }
}

// 6. 创建 use 函数
export const useUserStore = defineStore<UserState, UserStore>('user', new UserStore())

转换要点总结

原始 Pinia lime-pinia 说明
state: () => ({ ... }) state = reactive({ ... }) 使用 reactive
const name = ref(...) state.name 将 ref 合并到 state 对象
name.value this.state.name 去掉 .value
this.name this.state.name 通过 .state 访问
actions 中的方法 类方法,建议用 $action 包装 支持 $onAction 订阅
- 构造函数中调用 this.bindState(this.state) 必须

支持与赞赏

如果你觉得本插件解决了你的问题,可以考虑支持作者:

支付宝赞助 微信赞助

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。