Pinia
安装
1
npm install pinia
创建 Pinia 实例
1
2
3
4
5
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
createApp(App).use(createPinia()).mount('#app');
定义 Store
选项式
1
2
3
4
5
6
7
8
9
10
11
12
13
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0, name: 'xiaowhang' }),
getters: {
doubleCount: state => state.count * 2,
},
actions: {
increment() {
this.count++;
},
},
});
可以认为
state
是 store 的数据 (data
),getters
是 store 的计算属性 (computed
),而actions
则是方法 (methods
)。
组合式
1
2
3
4
5
6
7
8
9
10
11
12
13
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useCounterStore = defineStore('counter', () => {
const count = ref(0);
const name = 'xiaowhang';
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, doubleCount, increment };
});
在组合式 Store 中:
ref()
就是state
属性computed()
就是getters
function()
就是actions
State
state
是 store 的数据 (data
)
定义 State
1
2
3
4
5
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0, name: 'xiaowhang' }),
});
在组件中使用
1
2
3
4
5
6
7
8
9
10
11
<template>
<h2>当前计数为:{{ countStore.count }}</h2>
</template>
<script setup lang="ts">
// 引入对应的useXxxxxStore
import { useCounterStore } from '@/store/counter';
// 调用useXxxxxStore得到对应的store
const countStore = useCounterStore();
</script>
修改 State
直接修改
1
2
3
const countStore = useCounterStore();
countStore.count++
Patch 补丁
1
2
3
4
5
store.$patch({
count: store.count + 1,
age: 120,
name: 'DIO',
})
Action
Action
相当于组件中的method
。它们可以通过defineStore()
中的actions
属性来定义,并且它们也是定义业务逻辑的完美选择。
定义 Action
1
2
3
4
5
6
7
8
9
10
11
12
13
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++;
},
randomizeCounter() {
this.count = Math.round(100 * Math.random());
},
},
});
调用 Action
1
2
3
4
5
6
7
8
9
10
<template>
<h2>当前计数为:{{ countStore.count }}</h2>
<button @click="countStore.increment()">计数增加</button>
</template>
<script setup lang="ts">
import { useCounterStore } from '@/store/counter';
const countStore = useCounterStore();
</script>
Getter
Getter
完全等同于 store 的state
的计算值。可以通过defineStore()
中的getters
属性来定义它们。推荐使用箭头函数,并且它将接收state
作为第一个参数
定义 Getter
1
2
3
4
5
6
7
8
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 1 }),
getters: {
doubleCount: state => state.count * 2,
},
});
在组件中使用
1
2
3
4
5
6
7
8
9
10
<template>
<h2>当前计数为:{{ countStore.count }}</h2>
<h2>翻倍后为: {{ countStore.doubleCount }}</h2>
</template>
<script setup lang="ts">
import { useCounterStore } from '@/store/counter';
const countStore = useCounterStore();
</script>
storeToRefs
借助 storeToRefs
将 store
中的数据转为 ref
对象,方便在模板中使用(保留响应式)。
1
2
3
4
5
6
7
8
9
10
11
12
<template>
<h2>当前计数为:{{ count }}</h2>
<h2>翻倍后为: {{ doubleCount }}</h2>
</template>
<script setup lang="ts" name="Count">
import { useCounterStore } from '@/store/counter';
import { storeToRefs } from 'pinia';
const countStore = useCounterStore();
const { count, doubleCount } = storeToRefs(countStore);
</script>
订阅 state
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<h2>当前计数为:{{ count }}</h2>
<h2>翻倍后为: {{ doubleCount }}</h2>
</template>
<script setup lang="ts" name="Count">
import { useCounterStore } from '@/store/counter';
import { storeToRefs } from 'pinia';
const countStore = useCounterStore();
const { count, doubleCount } = storeToRefs(countStore);
countStore.$subscribe((mutation, state) => {
console.log(mutation, state);
// 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('cart', JSON.stringify(state));
});
</script>
Pinia
http://xiaowhang.github.io/archives/1960634197/