手写pinia与思想

49 阅读3分钟

手写pinia与思想

pinia

pinia是伴随着vue3的状态管理库,具有可扩展性与类型安全的特点。也就是支持插件和typescript。

手写pinia

const piniaSymbol = Symbol('pinia')
// symbol全局唯一key,避免重复
function createPinia() {
    // pinia  全局的pinia
    let pinia = {
        // app.use(pinia) 这个方法在执行之后会调用pinia的install方法完成安装 
        // 至于app参数就是将vue的createApp创建出来的实例的this
        install(app) {
            app.poride(piniaSymbol, pinia)
            state: ref({})
            // store内的state
            _s: new Map()
            // 存储每个store
        }
    }
    return pinia
}

// 定义store,组件中通过对象的点语法调用state/getter等
function defineStore(id, options) {

    function useStore() {
        // 高阶函数  函数执行完成后返回store实例
        let pinia = inject(piniaSymbol)
        // 提取pinia实例
        if (!pinia._s.get(id)) {
            // 是否存在重复id的store,重复则直接获取已有的store,否则创建store
            createOtionStore(id, options, pinia)
        }
        let store = pinia._s.get(id)
        return store
    }
    return useStore
}

function createOtionStore(id, options, pinia) {
    // const { state, ggetters, actions } = options
    let store = reactive({
        _p: pinia,
        id
    })
    Object.assign(store, setup())
    pinia._s.set(id, store)
    function setup() {
        const { state, getters, actions } = options
        // 判断 pinia.state.value 中是否有值,如果没值则将 state 的调用结果赋值进去
        !pinia.state.value[id] && (pinia.state.value[id] = state())
        // 此时通过 toRefs 将 pinia.state.value[id] 处理为响应式
        let localState = toRefs(pinia.state.value[id])
        // 处理getters 时先拿到内部所有的 key 组成的数组

        let localGetters = Object.keys(getters).reduce((item, name) => {
            // 通过computed,调用时,将this指向store即可完成读取state
            item[name] = computed(() => {
                const store = pinia._s.get(id)
                return getters[name].call(store, store)
            })
            return item
        }, {})

        // 此处将 处理后的 state/getters/actions 返回
        return Object.assign(localState, localGetters, actions)
    }


}

主要由四个大块组成:

  1. piniaSymbol:symbol的全局变量,唯一的key,避免重复。
  2. createPinia:用于创建pinia,外部应用使用pinia时,调用pinia内部的install方法即可。它内部使用依赖注入,为外部应用提供pinia对象。且pinia有响应式的state和map结构的stroe集合。
  3. defineStore:是一个高阶函数,函数执行返回store实例。在这里会提取到pinia的实例,将pinia上的map的store集合设置值。
  4. createOtionStore:完成上方的pinia上的map的设置store的操作。首先store实例是响应式的,有唯一id,然后将传入的options处理后添加到store实例上。options操作state通过pinia,然后compute作为store上的各类方法。

pinia本身还支持插件,例如持久化的插件,然后就是pinia现在不仅支持options式的api,还可以setup式的,但也就是createOptionsStore换成createSetupStore罢了。他们的内部处理不同系统。

思想

前端的中间件:中间件在后端是耳熟能详的,一般来说也就是扩展项目的插件。在前端其实也差不多,特点就是:调用函数方法创建实例,然后设置实例的一些状态或者拦截器(vueRouter的拦截器),最后外部应用调用实例的install方法就可以了。

前端来说中间件或者应该叫中间件模式,应用的是中间件的思想。

前端插件的中间件比如express,koa,pinia。其实axios也是中间件的思想,特别是封装过的。

然后就是中间件通过symbol来完成依赖注入,全局的设置插件。

其次中间件通过高阶函数的形式返回实例。

以上就是pinia引出的一些思想,学习它主要是pinia具有足够的代表性,且前端来说插件基本上都是使用了中间件这样的思想来完成。

结语

本次的文章到这里就结束啦!♥♥♥读者大大们认为写的不错的话点个赞再走哦 ♥♥♥

每天一个知识点,每天都在进步!♥♥