Pinia 部分源码浅析
概述
Pinia
中只用到了 vue-demi 一种库,vue-demi 的介绍可以参考 vue-demi。
Pinia
可以在 vue2 和 vue3 中用于数据或状态的管理,同时 pinia 还提供了极其丰富的浏览器调试插件工具,更多详细内容可以参考 Pinia 官网。
vue2 中使用 Pinia
pinia
提供了PiniaVuePlugin
,在 vue2 中需要手动注册
import Vue from "vue";
import {
PiniaVuePlugin, createPinia } from "pinia";
Vue.use(PiniaVuePlugin);
const pinia = createPinia();
new Vue({
el: "#app",
// ...
pinia,
});
PiniaVuePlugin
原理
PiniaVuePlugin
是一个函数,注册时会被作为 install 方法,接收传入的参数 Vue,然后再通过Vue.mixin
全局混入breforeCreate
和destroyed
这两个生命周期钩子函数,影响到每一个 Vue 实例。
breforeCreate
在这个钩子中 将选项中的 pinia 实例挂载到 vue 上。
beforeCreate() {
...
this._provided[piniaSymbol]=pinia
this.$pinia = pinia;
pinia._a=this //将vue挂载到pinia上,方便于pinia注册插件
...
}
destroyed
在销毁组件时,将组件实例从 pinia 实例中移除。
vue3 中使用 Pinia
vue3 中使用 Pinia 需要先调用createPinia
创建 Pinia 实例,返回 pinia 对象,再手动注册 Pinia 实例。
createPinia
创建 Pinia 实例
createPinia
函数是Pinia
的核心函数,它返回一个Pinia
实例,该实例包含install
方法,用于安装Pinia
插件,以及use
方法,用于注册插件,比如数据持久化插件piniaPluginPersistedstate
createPinia
首先通过vueDemi.effectScope
创建一个独立的作用域scope
,再通过scope.run
方法返回一个vueDemi.ref({})
ref 对象作为state
由上可知 vue2 中使用Pinia
也会调用createPinia
方法创建实例,因此在install
属性方法中 Pinia 判断了当前环境是否是 vue2,如果不是,则执行app.config.globalProperties.$pinia = pinia;
将 pinia 实例挂载到 vue 实例上
export function createPinia() {
const pinia =vueDemi.markRaw({
install:(app)=>{
/*...*/},
use:(plugin)=>{
/*...*/},
_p,// 需要通过pinia.use的插件集合
_a:null // 指向vue