pinia源码解读一(初始化)

初始化 createPinia.ts

主要有3步

  • effectScope生成了一个作用域在内部调用ref({})用来存储所有模块的state

  • 创建了一个pinia实例,里面包含了use和install方法和一些关键属性

    install内部使用vue的provide来传递pinia实例

    use用来注册pinia插件

    _s属性通过map存储所有模块的store

    _e属性是整个pinia实例的作用域

    state存储所有store的state

  • 判断是否需要注册pinia插件来适配vue-devtool

下面是简化过的代码

export function createPinia(): Pinia {
  const scope = effectScope(true)
  // 这个state是存储了所有的模块的state
  const state = scope.run<Ref<Record<string, StateTree>>>(() =>
    ref<Record<string, StateTree>>({})
  )!

  let _p: Pinia['_p'] = []
  // plugins added before calling app.use(pinia)
  let toBeInstalled: PiniaPlugin[] = []

  const pinia: Pinia = markRaw({
    install(app: App) {
      setActivePinia(pinia)
      if (!isVue2) {
        pinia._a = app
        // 注入pinia实例
        app.provide(piniaSymbol, pinia)
        app.config.globalProperties.$pinia = pinia
        if (USE_DEVTOOLS) {
          registerPiniaDevtools(app, pinia)
        }
        toBeInstalled.forEach((plugin) => _p.push(plugin))
        toBeInstalled = []
      }
    },

    use(plugin) {
      if (!this._a && !isVue2) {
        // 注册pinia插件
        toBeInstalled.push(plugin)
      } else {
        _p.push(plugin)
      }
      return this
    },

    _p,
    // it's actually undefined here
    _a: null,
    _e: scope,
    // pinia的所有模块在这里存储
    _s: new Map<string, StoreGeneric>(),
    state,
  })

  // 内部适配vue-devtool的pinia插件
  if (USE_DEVTOOLS && typeof Proxy !== 'undefined') {
    pinia.use(devtoolsPlugin)
  }

  return pinia
}

posted @ 2022-11-28 16:01  爱吃巧克力的狗  阅读(228)  评论(0编辑  收藏  举报