Language: 中文简体 | EN
genji
是一个轻巧的基于 @vue-reactivity
开发的 vue3
状态管理框架.
灵感来自于游戏《守望先锋》
的游戏角色:源氏
。
源氏可以用致命而准确的手里剑重创敌人,他的高科技武士刀可以用来反弹敌人的远程攻击,或是对敌人施展一次快速攻击。
所以 genji
是快速的、敏捷的、准确的!
pnpm install @xieyezi/genji
你的 Store
是一个基于compostion-api
的 hook
!您可以在其中添加任何内容:普通类型,对象,函数。 set
函数会将他们合并为一个 Store
。
import { create } from '@xieyezi/genji'
const useStore = create((set, get) => ({
count: 0,
increase: () => set(state => ({ count: state.count + 1 })),
resetCount: () => set({ count: 0 })
}))
在你的组件中使用这个 hook
,取出你想要的值,组件将在更新 state
之后重新渲染。
<template>
<p>count is: {{ count }}</p>
<button @click="increase">count++</button>
</template>
....
setup() {
const { count, increase } = useStore(state => ({
count: state.count,
increase: state.increase
}))
return {
count,
increase,
}
}
你可以按照自己喜欢的方式取出你想要的值。
如果你想一个一个取出来:
const count = useStore(state => state.count)
const genji = useStore(state => state.genji)
如果你想用对象的方式取值(类似vuex mapState
):
// Object pick, re-renders the component when either state.count or state.genji change
const { count, genji } = useStore((state) => ({
count: state.count,
genji: state.genji
}))
如果你想用数组的方式取值(类似react hooks
):
// Array pick, re-renders the component when either state.count or state.genji change
const [count, genji] = useStore(state => [state.count, state.genji])
甚至你还可以不带任何参数,直接取出来:
// uses the store with no args
const { count, increase } = useStore()
所有取值方式都是如此简单!这一切都取决于你怎么创建你的选择器
。
由于你可以创建任意数量的 Store
,因此你可以随意组合各个Store
里面的值。
import useUserStore from '../store/user'
import useOrder from '../store/order'
const name = useUserStore(state => state.name)
const orders = useOrder(state => state.orders)
在 vue
中,通常来说,一般都建议利用 computed
来构造你的选择器。
但是需要注意,此时从
Store
中选择的值需要用unref
包装,因为状态的值由Proxy
代理。
const countDouble = useStore(state =>computed(()=>unref( state.count) * 2))
如果选择器
不在组件中使用,则也可以在组件外部定义它。但是,当使用来自 Store
的选择值时,也需要使用 unref
进行包裹,或者你也可以直接利用 .value
来使用它。
const selector = state => state.hero
const hero = useStore(selector)
// warpped with unref()
console.log(unref(hero))
// or you can use like this:
console.log(hero.value)
genji
提供 set
函数来更新“状态”。就像这样:
const useStore = create((set, get) => ({
count: 0,
increase: () => set(state => ({ count: state.count + 1 })),
}))
const { count, increase } = useStore(state => ({
count: state.count,
increase: state.increase
}))
接着你就可以使用 increase
函数去改变 count
。
对于异步任务,建议使用
async/await
来处理。
const useStore = create((set, get) => ({
userInfo: {},
getUserInfo: async () => {
const res = await fetch(pond)
set({ userInfo: res })
}
}))
在一个 action
执行过程中,如果你想取出 Store
的某些值,你可以通过 get
钩子来访问Store
。
const useStore = create((set, get) => ({
hero: 'genji',
action: () => {
const hero = get().hero
// ...
}
})
// 可以使用 `type`
type State = {
count: number
increase: (by: number) => void
}
// 或者 `interface`
interface State {
count: number
increase: (by: number) => void
}
// 然后所有的类型都会被正确推导
const useStore = create<State>(set => ({
count: 0,
increase: (by) => set(state => ({ count: state.count + by })),
}))
喜欢你能喜欢genji
~
api usage inspired by zustand, thanks a lot!