前言
之前已经通过读文档,写demo,知道了pinia怎么用,今天,来研究下pinia是怎么实现的
程序入口
通过script中的build命令找到rollup配置文件
从打包配置可以看出其入口为src下的index
向vue注册(初始化)
示例代码
通过vue的插件机制,允许向整个应用程序注册全局共享的功能,写法一般固定为对象内含install方法,由于pinia同时支持vue2和vue3,在入口处其暴漏了PiniaVuePlugin和createPinia来分别实现插件注册
PiniaVuePlugin
该函数利用mixins api向组件混入了beforeCreate周期钩子,由于vue在组件实力化过程中会先读取全局的mixins并会经过一次配置合并过程,其中对生命周期的合并策略是数组的push,故每一个组件实例初始化过程中都会callhook到beforeCreate
如下框红所示,每一个组件实例中都将通过this访问到pinia实例
createPinia
与vue2不同的是,vue3中通过provide+inject的方式向子孙组件注入
定义、使用子模块store
示例代码
调用createPinia时,会向全局创建一个空对象作为根store,在组件使用时则对外提供了defineStore来定义组件的store,这实际是在向根store做“add”操作
示例代码
执行定义函数调用后返回的useStore方法,会首先获取到根store,接着将定义的本模块的store设置到根store上并返回
store的创建过程
示例代码
承接上例
不管是option api形式还是setup形式,最终走的都是createSetupStore,在源码层面对option形式做了次转换
而store的创建过程其实分为两部分:解析并挂载定义的store、为store装饰api
解析与挂载流程
装饰api
这个比较简单,就是将内部的函数挂载到对象上并return出去即可
api相关
$reset
该api是$patch的语法糖,只不过传递的参数是初始的state函数的执行结果
$patch
patch就是一次递归对value覆盖的过程
$subscribe
有点类似观察者,当调用subscribe时,会将当前的状态信息保存到subscriptions
此时,只需要在调用修改store相关的api时,拿到subscriptions的数组依次run一遍即可
插件机制
通过pinia.use向pinia实例的_p属性做缓存
接着,在创建store时将store传递给插件并执行,如下extender即调用插件的初始化逻辑