@free-walk/svelte-store
v1.5.0
Published
Pinia 风格的 Svelte 5 状态管理库,基于 svelte/store 构建
Maintainers
Readme
svelte-store
Pinia 风格的 Svelte 5 状态管理库,基于 svelte/store 构建。
特性
- 🏪 Pinia 风格 API —
defineStore定义 store,支持 Options API 和 Setup 风格 - 📦 基于 svelte/store — 完全兼容 Svelte 生态,支持
$store自动订阅 - 🔌 插件系统 — 支持全局插件,可扩展持久化、日志等功能
- 🎯 TypeScript — 完整类型推导
- ⚡ 轻量 — 零额外依赖,仅依赖
svelte/store
安装
npm install svelte-store快速开始
Options API 风格
import { defineStore } from 'svelte-store'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
name: 'Counter',
}),
getters: {
doubleCount: (state) => state.count * 2,
displayName: (state) => `${state.name}: ${state.count}`,
},
actions: {
increment() {
this.$patch({ count: this.$state.count + 1 })
},
decrement() {
this.$patch({ count: this.$state.count - 1 })
},
incrementBy(amount: number) {
this.$patch({ count: this.$state.count + amount })
},
},
})Setup 风格
import { defineStore, writable, derived } from 'svelte-store'
export const useCounterStore = defineStore('counter', () => {
const count = writable(0)
const doubleCount = derived(count, ($count) => $count * 2)
function increment() {
count.update((n) => n + 1)
}
function decrement() {
count.update((n) => n - 1)
}
return { count, doubleCount, increment, decrement }
})在组件中使用
<script>
import { useCounterStore } from '../stores/counter'
const counter = useCounterStore()
</script>
<p>Count: {counter.$state.count}</p>
<p>Double: {counter.doubleCount}</p>
<button onclick={() => counter.increment()}>+</button>
<button onclick={() => counter.decrement()}>-</button>Store 实例 API
| 方法 / 属性 | 说明 |
|---|---|
| $id | Store 的唯一标识字符串 |
| $state | 获取当前 state 快照 |
| $patch(partial) | 批量更新 state(对象或函数) |
| $reset() | 重置 state 到初始值(仅 Options API) |
| $subscribe(callback) | 监听 state 变化(跳过初始值,仅在变更时触发) |
| $dispose() | 销毁 store,清理所有内部订阅 |
| $onAction(callback) | 监听 action 调用,支持 after/onError 钩子 |
| subscribe(run) | svelte/store 标准订阅接口 |
$patch 用法
// 对象方式
counter.$patch({ count: 10 })
// 函数方式
counter.$patch((state) => {
state.count++
state.name = 'Updated'
})$subscribe 用法
const unsubscribe = counter.$subscribe((state) => {
console.log('state 变化:', state)
})
// 需要时取消订阅
unsubscribe()$onAction 用法
const unsubscribe = counter.$onAction(({ name, args, after, onError }) => {
console.log(`Action "${name}" 被调用,参数:`, args)
after((result) => {
console.log(`Action "${name}" 执行成功:`, result)
})
onError((error) => {
console.error(`Action "${name}" 执行失败:`, error)
})
})$dispose 用法
// 销毁 store,清理所有订阅
counter.$dispose()storeToRefs
将 store 属性转为独立的 Readable store(类似 Pinia 的 storeToRefs):
import { storeToRefs } from '@free-walk/svelte-store'
const counter = useCounterStore()
const { count, doubleCount } = storeToRefs(counter)
// count 是 Readable<number>,doubleCount 是 Readable<number>插件系统
import { addPlugin } from 'svelte-store'
// 持久化插件示例
addPlugin(({ store, storeId }) => {
// 恢复持久化数据
const key = `svelte-store-${storeId}`
const saved = localStorage.getItem(key)
if (saved) {
try {
store.$patch(JSON.parse(saved))
} catch {}
}
// 监听变化并持久化
store.$subscribe((state) => {
localStorage.setItem(key, JSON.stringify(state))
})
})
// 日志插件示例
addPlugin(({ store, storeId }) => {
store.$subscribe((state) => {
console.log(`[${storeId}]`, state)
})
})辅助函数
mapState
从 store 中提取状态为独立的 Readable store:
import { mapState } from 'svelte-store'
const { count, name } = mapState(useCounterStore, ['count', 'name'])
// count 和 name 是 Readable<number> 和 Readable<string>mapActions
从 store 中提取 actions 为独立函数:
import { mapActions } from 'svelte-store'
const { increment, decrement } = mapActions(useCounterStore, ['increment', 'decrement'])
increment() // 直接调用兼容性
| 格式 | 文件 | 用途 |
|---|---|---|
| ESM | dist/svelte-store.mjs | import 语法 |
| CJS | dist/svelte-store.cjs | require() 语法 |
| Svelte 源码 | src/index.ts | Svelte 项目直接引用 |
License
MIT
