| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- import { reactive, isRef, isReactive, toRaw, ComputedRef, toRef, effectScope, unref } from 'vue'
- import { v4 } from 'uuid'
- import { Store, StoreState, StoreToRefs } from './types'
- /**
- * 判断是否 ComputedRef 类型
- * @param obj
- * @returns
- */
- function isComputed(obj: unknown): obj is ComputedRef {
- return !!(isRef(obj) && Reflect.has(obj, 'effect'))
- }
- /**
- * 定义一个 store 对象
- * @param createStore
- * @param id
- * @returns
- */
- export function defineStore<T extends object>(createStore: () => T, id = v4()) {
- const scope = effectScope()
- const store = scope.run(() => createStore()) as T
- // 将 store 中的响应式属性转化为 ref 属性
- const $toRefs = () => {
- const result = Object.create(null)
- for (const key in store) {
- const value = store[key]
- if (isRef(value)) {
- result[key] = value
- } else if (isReactive(value)) {
- result[key] = toRef(store, key)
- }
- }
- return result as StoreToRefs<T>
- }
- // 更新 state 状态
- const $setState = (callback: (state: StoreState<T>) => void) => {
- const state = Object.create(null)
- for (const key in store) {
- const value = store[key]
- if (!isComputed(value) && (isRef(value) || isReactive(value))) {
- state[key] = value
- }
- }
- callback(reactive(state))
- }
- // 将 state 重设为初始状态
- const $reset = () => {
- const newScope = effectScope()
- const newStore = scope.run(() => createStore()) as T
- for (const key in store) {
- const item = store[key]
- if (!isComputed(item) && isRef(item)) {
- item.value = unref(newStore[key])
- }
- if (isReactive(item)) {
- for (const prop in item) {
- item[prop] = newStore[key][prop]
- }
- }
- }
- newScope.stop()
- }
- // 销毁当前的 store
- const $dispose = () => {
- scope.stop()
- }
- const $store: Store<T> = reactive({
- $id: id,
- $toRefs,
- $setState,
- $reset,
- $dispose,
- ...store
- })
- return () => $store
- }
- /**
- * 将 store 中的响应式属性转化为 ref 属性
- * @param store
- * @returns
- */
- export function storeToRefs<T extends object>(store: Store<T>) {
- const raw = toRaw(store)
- const result = Object.create(null)
- for (const key in raw) {
- const value = raw[key]
- if (isRef(value)) {
- result[key] = value
- } else if (isReactive(value)) {
- result[key] = toRef(raw, key)
- }
- }
- return result as StoreToRefs<T>
- }
|