与Vuex的区别
- vuex的同步操作用mutatuins,异步操作用actions,太麻烦
- pinia没有mutations,同步异步都用actions
- 版本问题
- vuex的最新版本4.x
- vuex4用于vue3
- vuex3用于vue2
- pinia最新版本2.x
- 既支持vue2也支持vue3
- vuex的最新版本4.x
- pinia没有命名空间模块
- pinia更好的支持ts
基本使用
pinia的核心配置
- state
- actions 同步异步都支持
- getters
安装pinia
npm i pinia
使用pinia
// main.ts
import { createApp } from 'vue'
import {createPinia} from "pinia
// 创建pinia实例
const pinia = createPinia()
createApp(App).use(pinia).mount('#app')
// store/index.ts
import { defineStore } from 'pinia'
interface IState {
count: number
name: string
isAdmin: boolean
items: Array<any>
info: {
age: number
}
}
/**
* @desc
* 定义并导出容器
* 参数一:容器的 ID,必须唯一,pinia会把所有容器挂载到跟容器上
* 参数二:配置选项
* 返回值:一个函数,调用后返回容器实例
*/
export const useMainStore = defineStore('main', {
/**
* @desc
* 1. state是一个返回初始状态的函数
* 2. 推荐使用箭头函数,为了更好的TS类型推断
*/
state: (): IState => ({
// 所有这些属性都将自动推断出它们的类型
count: 0,
name: 'Eduardo',
isAdmin: true,
items: [],
info: {
age: 18
}
}),
})
在组件中获取 state 中的状态
// Demo.vue
<template>
<h1>Pinia</h1>
<!-- 在模板中使用 -->
mainStore.count : {{ mainStore.count }}
<!-- 解构获取store中的状态 -->
count : {{ count }} name : {{ name }}
<br />
info:{{ info }}
<br />
<button @click="mainStore.info.age++">按钮</button>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { useMainStore } from "./store/index";
export default defineComponent({
setup() {
// 获取容器实例
const mainStore = useMainStore()
// 获取store中的状态
console.log(mainStore.count); // 0
// 解构获取store中的状态
//#region
// 对于基本数据类型的解构的错误写法
// const { count, name } = mainStore;
// 因为 proxy 只能代理引用类型数据
// {
// count: 0,
// name: 'Eduardo',
// isAdmin: true,
// }
// proxy 代理了整个对象,而对于对象里面的基本数据类型并不能代理,所以解构出来的基本数据类型不是响应式的
//#endregion
// 1. 解构基本数据类型
const { count, name } = storeToRefs(mainStore);
console.log(count.value); // 0
// 2. 解构对象类型
// 写法一
const { info } = storeToRefs(mainStore);
// 写法二
// const { info } = mainStore; // info是引用数据类型,被递归代理proxy
return { mainStore, count, name, info };
},
});
</script>
修改state中的状态
<script lang="ts">
import { defineComponent } from "vue";
import { useMainStore } from "./store/index";
import { storeToRefs } from "pinia";
export default defineComponent({
setup() {
const mainStore = useMainStore();
const { count, name, info } = storeToRefs(mainStore);
// 修改store中的状态
const handleStore = () => {
// 单个修改
mainStore.count = 10;
// 批量修改
// 写法一 $patch函数的参数为对象,有内部优化
mainStore.$patch({
count: 10,
name: "jack Chen",
items: [...mainStore.items, 3],
});
// 写法二 $patch函数的参数为回调函数
mainStore.$patch((state) => {
state.count = 10;
state.name = "jack Chen";
state.items.push(3);
});
// 逻辑比较多时,使用actions修改
mainStore.changeState({ num: 10 });
};
return { mainStore, count, name, info };
},
});
</script>
// store/index.ts
import { defineStore } from 'pinia'
interface IState {
count: number
name: string
isAdmin: boolean
items: Array<any>
info: {
age: number
}
}
export const useMainStore = defineStore('main', {
state: (): IState => ({
// 所有这些属性都将自动推断出它们的类型
count: 0,
name: 'Eduardo',
isAdmin: true,
items: [1, 2],
info: {
age: 18
}
}),
actions: {
// 不能使用箭头函数定义changeState
changeState<T extends { num: number }> (payload: T) {
// 单个修改
this.count = payload.num
// 批量修改
// this.$patch({})
this.$patch(state => {
state.name = 'jack Chen'
state.items.push(4)
})
}
}
})