认识
一、认识
Pinia
主要通过两个 API
来实现高效、灵活的状态管理解决方案。
-
createPinia
: 基于effectScope
创建一个effect
作用域, 并传入ture
, 阻断和父级的联系。独立收集收集和管理副作用。使用ref
创建一个响应式对象state
, 这是Pinia store
的状态对象。通过scope.run()
将其运行在之前创建的效果作用域中,意味着state
的所有响应式变更都将被该作用域管理。基于markRaw
创建并标记一个Pinia
对象, 避免其状态管理逻辑被Vue
追踪。Pinia
对象中有一个install
方法、_a
、_e
、_s
属性。作用如下:-
instanll
:Pinia
暴露给Vue
应用的接口,用于安装Pinia
插件。内部会为Pinia
建立一个Symbol
唯一标识, 基于app.provide
注入到根组件实例中。 -
_a
: 存储Vue
应用实例,通常用于内部访问Vue
应用上下文 -
_e
: 存储之前创建的效果作用域 -
_s
: 一个存储所有store
实例的映射,用于管理和访问应用中的所有状态存储
-
-
defineStore
: 以独一无二的storeId
基于传入的对象或者函数创建store
。 内部会定义一个useStore
函数, 函数内部首先通过getCurrentInstance
获取当前组件实例, 通过inject
获取之前注入的Pinia
对象。判断Pinia._s
中是否存在传入的storeId
对象, 如果存在, 直接返回storeId
对应的store
, 如果不存在, 创建storeId
对应的store
,传入对象、或者函数会走不同的逻辑来创建。其中, 函数的创建逻辑为: 创建一个响应式对象store
, 因为每一个storeId
对应着自己的store
。在pinia._e
父级作用域中, 创建一个子作用域, 在子作用域中运行传入的函数,storeId
对应的store
函数产生的副作用由子作用域来管理。得到了一个作用域中产生的store
。对这个store
中的函数进行包装, 主要是将this
指向改变为当前的store
。最后合并store
与作用域中产生的store
, 并更新pinia._s
二、工作流
Pinia
基于 Vue.js 3.0
提供的 effectScope
实现新的状态管理方式。实现如下:
1. 定义 defineStore
, 基于 effectScope
创建一个 effect
作用域, 在这个作用域中管理传入的 store
import { effectScope } from "vue";
function defineStore(setup){
let state;
let isChange = false;
const scope = effectScope(true);
return ()=>{
if(!isChange){
state = scope.run(setup);
isChange = true;
}
return state;
}
}
export default defineStore;
2. 定义 useStore
, 基于 defineStore
, 传入一个回调函数, 回调函数内部就是我们的 store
import { computed, ref } from "vue";
import defineGlobalStore from "./defineStore";
const useStore = defineGlobalStore(() => {
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
const updateCount = () => {
count.value++;
};
return { count, doubleCount, updateCount };
});
export default useStore;
3. 随后, 我们就可以在不同的组件中使用 useStore
来进行子父组件、兄弟组件、全局通信