示例项目克隆: https://gitee.com/yyt363045841/example-of-pintia-project.git
什么是 Pinia
- 一个状态管理库
- 类似:redux,vuex
- 集中式状态管理:不同组件的数据共享(但不是所有数据)
- 处理的是一个
reactive响应式对象
启用 pinia
ts
const app = createApp(App)
app.use(createPinia())//创建并安装此时控制台会输出 "count" store installed (在组件中调用 useXXXStore 的 export 函数的时候)。
定义 pinia 存储仓库
在 .src/store 中存储 pinia 数据。
ts
import { defineStore } from "pinia";
export const useCountStore = defineStore('count',{
state:()=>{
return {
sum:6
}
}
})在组件中读取数据
ts
let useTalkStore = useLovetaikStore()//调用暴露函数获取数据渲染
html
<div class="talk">
<button @click="getAword">get a word</button><br>
<ul v-if="useTalkStore.talklist.length > 0">
<li v-for="word in useTalkStore.talklist" :key="word.id">{{ word.title }}</li>
</ul>
</div>[[响应式基础#特例]]:虽然 useXXX 其中的数据是 ref 对象,但是在 reactive 中这个对象中的值的调用会被自动解包。
类型标注
ts
import { defineStore } from "pinia";
interface GameData {
nowChoose: number | null;
alertShow: boolean;
}
export const useGameData = defineStore("windowShow", {
state: (): GameData => ({//类型注解
nowChoose: null,
alertShow: false
})
});修改数据
- 直接修改拿到的
store对象属性
ts
const countStore = useCountStore();//获取store
function doAdd() {
countStore.sum += add.value;
}- 使用
$patch方法,同时应用多个修改
ts
function doAdd() {
countStore.$patch({
sum: countStore.sum + add.value,
});
}- 调用
store.action中定义的方法(进行逻辑处理、复用)
ts
import { defineStore } from "pinia";
export const useCountStore = defineStore('count',{
actions:{
increment(value:number){
this.sum++
}
},
state:()=>{
return {
sum:6
}
}
})ts
function doAdd() {
countStore.increment(add.value);
}storeToRefs
解构 store 数据的时候,不要用 toRefs,因为他会把 store 对象中的所有数据都变为响应式的。 使用 storeToRefs,可以只得到解构的响应式对象。
getters
相当于计算属性,不要将异步逻辑写在这里!
- 用于对
pinia管理的数据进行再次加工(封装计算逻辑) - 一旦
state状态更新,getter会自动更新 - 确保
state只存储基本状态
ts
export const useCountStore = defineStore('count',{
actions:{
increment(value:number){
this.sum++
}
},
state:()=>{
return {
sum:6
}
},
getters:{
watchCount:int (state){
return state.sum * 10//随着sum的更新而更新,等价于return this.num * 10
}
watchCount:state => return state*10//箭头函数简写,但是不能用this
}
})pinia 中的数据所有组件都可以读取,这个 getter 也相当于可共享的计算属性
$subscribe
当 store 管理的状态发生改变时调用。
ts
countStore.$subscribe((mutation, state) => {
console.log(mutation, state);//
});浏览器本地数据存储
存储
ts
useTalkStore.$subscribe((mutation, state) => {
localStorage.setItem('talkList',JSON.stringify(state.talkList))
})读取
ts
export const useLovetalkStore = defineStore('lovetalk', {
state: (): { talkList: List[] } => ({
talkList:JSON.parse(localStorage.getItem('talkList') as string) || []
//getItem的返回值为string | null,因此要将返回类型断言为string以通过类型检查
//第一次进入本地存储并不存在该项,因此要将它初始化为[]空数组
})
});Store 的组合式写法
和 vue 组件相同,reactive,ref 定义响应式数据,正常写函数,最终将其 return 出去即可。
ts
import { reactive } from "vue";
export const useTalkStore = defineStore('loveTalk',()=>{
let talkList = reactive(JSON.parse(localStorage.getItem('talkList') as string) || []);
async function addTalk() {
const { data: { content: title } } = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json');
let obj: List = {
id: nanoid(),
title: title
};
talkList.push(obj);
}
return {
talkList,
addTalk
}
})调用
ts
import { useTalkStore } from '@/store/Lovetalk';
const talkStore = useTalkStore()
//调用方法即可actions
处理 store 的业务逻辑,可以用异步