pinia 简单实现

pinia 简单实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { computed, reactive } from "vue";

let piniaInstance;

function setActivePinia(pinia) {
piniaInstance = pinia;
}
function getActivePinia(pinia) {
return piniaInstance;
}

const piniaSymbol = Symbol('pinia')

/**
* pinia 是一个插件, 所以要返回一个带install的对象
* @returns
*/
export const createPinia = () => {
const pinia = {
install(app, options) {
setActivePinia(pinia);
app.config.globalProperties.$pinia = pinia;
app.provide(piniaSymbol, pinia)
},
cache: new Map()
}

return pinia;
}

function createOptionsStore(id, options, pinia) {
const { state, actions, getters } = options;

let store;
function setup() {
return Object.assign(
state(),
actions,
Object.keys(getters).reduce((computedGetters, name) => {
computedGetters[name] = computed(() => {
return getters[name].call(store);
})
return computedGetters;
}, {})
)
}

store = createSetupStore(id, setup, pinia);
return store;
}

function createSetupStore(id, setup, pinia) {
const store = reactive({
$reset: () => { },
$patch: () => { },
})

Object.assign(store, setup())
pinia.cache.set(id, store);

return store;
}

export function defineStore(id, options) {
function useStore() {
const pinia = getActivePinia();

if (!pinia.cache.has(id)) {
if (typeof options === 'function') {
createSetupStore(id, options, pinia);
} else {
createOptionsStore(id, options, pinia)
}
}

const store = pinia.cache.get(id);
return store;
}
return useStore;
}

pinia 是一个插件 , 所有在createPinia 的时候要返回一个带install方法的对象。

得益于composition api,只要使用了reactive 或者 ref 等响应式函数, 在组件里面使用store的时候就可以自动更新。

所有defineStore 的option 语法的state 函数。 要创建一个响应式对象使state里面的数据响应式。