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
}