pinia同样是一个Vue
状态管理工具,它和vuex有很多相似的地方。本质上他是vuex团队核心成员开发的,在vuex上面提出了一些改进。与vuex相比,pinia去除了vuex中对于同步函数Mutations和异步函数Actions的区分。直接在Actions中便能够使用同步和异步方法(在vuex的开发计划中也将会除去同步和异步的区分)。其次相比于vuex,pinia对于typescript的支持性更好,友好的devTools支持,pinia只有1kb,简化了很多方法的写法。由于vuex比较完善,因此,pinia更加适合小型项目,vuex更加适合大型项目。
//利用vue-cli创建一个pinia项目(这里选择创建vue3项目)
vue create pinia
//在项目中安装pinia
npm install pinia@next
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
//需要注意的是从pinia中结构出来的createPinia是一个函数,挂载需要先调用执行
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
import {defineStore} from 'pinia';
export const userTestStore = defineStore({//需要注意的是,defineStore返回的是一个回调方法
id:'test',//test是该状态管理的唯一标志也可以使用defineStore(id,{});的形式
state(){
return {
name:'hello pinia',
age:20
}
},
getters:{
testGetters(){
return this.name+'...';//直接利用this便能够获取到里面的内容不需要使用state中间对象
}
},
actions:()=>{
addAge:function(){
setInterval(()=>{
this.age++;
},1000)
}
}
})
//在状态管理工具中定义addAge函数
actions:{
addAge(gap){
this.age+=gap;
}
}
//组件中导入对应状态管理工具
import { userTestStore } from "./store";
const store = userTestStore();
const { addAge } = store;//解构出store实例里面的addAge方法
组件中使用
<div>output age:{{ store.age }}</div>
<button @click="addAge(10)">click for add age</button>
直接修改解构出来的 age是不ref类型,给出如下的错误案例:
<div>error:{{ age }}</div>
<button @click="test">change error age</button>
let { age } = store;
function test() {
console.log(" error add age");
age++;
}
解决方法,使用pinia里面的storeToRefs强转:
import { storeToRefs } from "pinia";
let { age } = storeToRefs(userTestStore());
function test() {
age.value++;//注意这里要加上.value因为被转化成了ref类型
}
//这样就能够是实现有效修改了
//store-name.ts
export const enum Names {
Test = 'Test'
}
// store.js
import { defineStore } from 'pinia'
// defineStore 调用后返回一个函数,调用该函数获得 Store 实体
import { defineStore } from "pinia";
import { Names } from "./store-name";
//定义的defineStore(),并且它需要一个唯一的名称,Names.Test名称抽离出去作为第一个参数传递
export const useTestStore = defineStore(Names.Test, {
state: () => ({ current: 1, name: '小满' }),
//computed:修饰一些值
getters: {
},
//methods:可以做同步异步,提交state
actions: {
setCurrent(type: boolean) {
//通过this指向属性
if (!type) return false
this.current++
}
}
})
// 在vue3中使用
<template>
<div>
pinia:{{ current }}---{{ Test.name }}
<button @click="setCur">set</button>
</div>
</template>
<script lang="ts" setup>
import { useTestStore } from './store';
const Test = useTestStore()
const current = computed(() => Test.current)
/**
* state的五种方式修改值
1.直接修改值
Test.current=2
2.通过$patch修改,支持单个或多个属性修改
Test.$patch({current:33})
3.$patch工厂函数方式
Test.$patch((state) => {
state.current = 99;
state.name = '范迪塞尔'
})
4.$state 缺点是必须修改整个对象
Test.$state = { current: 88, name: '123' }
5.action
Test.setCurrent()
*/
const setCur = () => {
// Test.current = 2
// Test.$patch({ current: 33 })
Test.$patch((state) => {
state.current = 99;
state.name = '范迪塞尔'
})
Test.$state = { current: 88, name: '123' }
Test.setCurrent(true)
}
</script>
<style lang = "scss" scoped>
</style>