阅读 6882

Vue3,我决定不再使用Vuex

在开发基于Vue3的项目中发现我们可以不再依赖Vuex也能很方便的来管理数据,只需要通过Composition Api可以快捷的建立简单易懂的全局数据存储.

创建State

通过reactive我们来创建state,暴露的IState是用来方便其他文件来接受State对象

import { reactive } from 'vue'

export interface IState {
    code: string
    token: string
    user: any
}

export const State: IState = {
    code: '',
    token: '',
    user: {}
}

export function createState() {
    return reactive(State)
}
复制代码

创建Action

我们来创建Action来作为我们修改State的方法

import { reactive } from 'vue'
import { IState } from './state'

function updateCode(state: IState) {
    return (code: string) => {
        state.code = code
    }
}

function updateToken(state: IState) {
    return (token: string) => {
        state.token = token
    }
}

function updateUser(state: IState) {
    return (user: any) => {
        state.user = user
    }
}

/**
 * 创建Action
 * @param state
 */
export function createAction(state: IState) {
    return {
        updateToken: updateToken(state),
        updateCode: updateCode(state),
        updateUser: updateUser(state)
    }
}
复制代码

通过暴露的IState我们也可以实现对State的代码访问.

创建Store

创建好StateAction后我们将它们通过Store整合在一起.

import { reactive, readonly } from 'vue'
import { createAction } from './action'
import { createState } from './state'

const state = createState()
const action = createAction(state)

export const useStore = () => {
    const store = {
        state: readonly(state),
        action: readonly(action)
    }

    return store
}
复制代码

这样我们就可以在项目中通过调用useStore访问和修改State,因为通过useStore返回的State是通过readonly生成的,所以就确认只有Action可以对其进行修改.

// 访问state
const store = useStore()
store.state.code

// 调用action
const store = useStore()
store.action.updateCode(123)
复制代码

这样我们就离开了Vuex并创建出了可是实时更新的数据中心.

持久化存储

很多Store中的数据还是需要实现持久化存储,来保证页面刷新后数据依然可用,我们主要基于watch来实现持久化存储

import { watch, toRaw } from 'vue'

export function createPersistStorage<T>(state: any, key = 'default'): T {
    const STORAGE_KEY = '--APP-STORAGE--'

    // init value
    Object.entries(getItem(key)).forEach(([key, value]) => {
        state[key] = value
    })
	
    function setItem(state: any) {
        const stateRow = getItem()
        stateRow[key] = state
        const stateStr = JSON.stringify(stateRow)
        localStorage.setItem(STORAGE_KEY, stateStr)
    }

    function getItem(key?: string) {
        const stateStr = localStorage.getItem(STORAGE_KEY) || '{}'
        const stateRow = JSON.parse(stateStr) || {}
        return key ? stateRow[key] || {} : stateRow
    }

    watch(state, () => {
        const stateRow = toRaw(state)
        setItem(stateRow)
    })

    return readonly(state)
}
复制代码

通过watchtoRaw我们就实现了statelocalstorage的交互.

只需要将readonly更换成createPersistStorage即可

export const useStore = () => {
    const store = {
        state: createPersistStorage<IState>(state),
        action: readonly(action)
    }

    return store
}
复制代码

这样也就实现了对Store数据的持久化支持.

文章分类
前端
文章标签