Pinia 是 Vue.js 的官方状态管理库,它提供了一种简洁且易于理解的方式来管理应用的状态。在这篇文章中,我们将通过构建一个简单的应用来深入了解 Pinia 的基本用法。
为什么使用 Pinia?
在 Vue 应用中,随着应用规模的增长,状态管理变得越来越重要。状态管理库如 Vuex 和 Pinia 可以帮助我们更好地组织和管理应用的状态。与 Vuex 相比,Pinia 提供了更现代、更简洁的 API,同时保持了高度的灵活性和可扩展性。
简洁的 API: Pinia 的 API 设计非常简洁,易于上手。
更好的性能: Pinia 利用 Vue 3 的 Composition API 和响应式系统,提供了更好的性能。
易于调试: Pinia 提供了强大的调试工具支持,方便开发者跟踪状态的变化。
易于集成: Pinia 轻量级的设计使其易于集成到现有的 Vue 项目中。
所需文件:
准备环境
安装pinia
npm install pinia
当前页面:main.js
我们来全局引入pinia
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
const app = createApp(App)
const store = createPinia()
app.use(store).mount('#app')
引入后在哪里我们都可以用这个了。
开始操作
当前页面:user.js
我们来创建 Pinia Store,在项目中创建一个名为 store 的文件夹,并在其中创建一个名为 user.js 的文件,用于定义用户相关的状态管理。
import {defineStore} from 'pinia'//是store的一部分
export const useUserStore=defineStore({
id:'user',
state:()=>{//数据源
return {
userInfo:{
name:'张三',
age:18,
sex:'boy'
}
}
},
actions:{//专门用来修改state
changeUserName(name){
this.userInfo.name=name
},
changeUserSex(sex){
this.userInfo.sex=sex
} ,
changeUserAge(n){
this.userInfo.age+=n
}
},
getters:{//仓库中的计算属性
afterAge(state){
return state.userInfo.age+10
}
}
})
代码解释
State
state: () => ({
userInfo: {
name: '张三',
age: 18,
sex: 'boy'
}
})
定义状态: state 是一个函数,它返回一个对象,该对象包含了 Store 的所有状态。
初始状态: 在这里我们定义了一个 userInfo 对象,它包含了用户的姓名、年龄和性别。
Actions
actions: {
changeUserName(name) {
this.userInfo.name = name
},
changeUserSex(sex) {
this.userInfo.sex = sex
},
changeUserAge(n) {
this.userInfo.age += n
}
}
修改状态:actions 是一个对象,它包含了可以改变 Store 状态的方法。因为 Store 中的数据会被多个组件使用,为了确保数据的一致性和安全性,不允许组件直接修改 Store 中的数据。相反,组件应该通过调用 Store 中定义的 actions 来间接修改状态。这种方法有助于维护状态的一致性,并使得状态管理更加清晰和可控。
方法解释:
changeUserName: 接受一个参数 name,用于更改 userInfo 中的 name 属性。
changeUserSex: 接受一个参数 sex,用于更改 userInfo 中的 sex 属性。
changeUserAge: 接受一个参数 n,用于增加 userInfo 中的 age 属性的值。
Getters
getters: {
afterAge(state) {
return state.userInfo.age + 10
}
}
计算属性: getters 是一个对象,它包含了基于 Store 状态计算得出的值。
方法解释: afterAge 方法返回用户当前年龄加上 10 的结果。
当前页面:App.vue
接下来,在 App.vue 文件中,我们可以使用 <script setup> 语法来引入和使用 useUserStore:
<template>
<User/>
<UpdateUser/>
</template>
<script setup>
import User from './components/User.vue'
import UpdateUser from './components/Update-user.vue'
</script>
<style lang="scss" scoped>
</style>
当前页面:User.vue
在 User.vue 组件中,我们可以直接访问 Store 中的状态和计算属性:
<template>
<ul>
<li>姓名:{{ userStore.userInfo.name }}</li>
<li>年龄:{{ age }}</li>
<li>十年后的年龄:{{ userStore.afterAge }}</li>
<li>性别:{{ userInfo.sex }}</li>
</ul>
</template>
<script setup>
import { useUserStore } from '@/store/user';
import { computed } from 'vue';
import { storeToRefs } from 'pinia';
const userStore=useUserStore()
const age=computed(()=>userStore.userInfo.age)
const {userInfo}=storeToRefs(userStore)//把整个仓库的数据源变成响应式的
</script>
<style lang="scss" scoped>
</style>
代码解释
导入 Store: 我们从 store/user.js 文件中导入 useUserStore 函数。
转换为响应式引用: storeToRefs 函数将 Store 中的状态转换为响应式引用。这样,我们可以直接在模板中访问这些状态。
创建计算属性: 使用 computed 函数创建一个计算属性,它返回用户的年龄。
当前页面:UpdateUser.vue
在 UpdateUser.vue 组件中,我们可以使用 Store 中的动作来更新用户信息:
<template>
<div>
<button @click="changeName">修改仓库中的用户名字</button>
<button @click="changeAge">修改仓库中的用户年龄</button>
<button @click="changeSex">修改仓库中的用户性别</button>
</div>
</template>
<script setup>
import {useUserStore} from "@/store/user";
const userStore =useUserStore();
const changeName = () => {
userStore.changeUserName('李四')
}
const changeSex=()=>{
userStore.changeUserSex('gril')
}
const changeAge=()=>{
userStore.changeUserAge(1)
}
</script>
<style lang="scss" scoped>
</style>
代码解释
方法修改库中数据(也就将User.vue中展出的数据进行了修改): 在这里我们定义了一个方法 changeName,它调用 changeUserName 方法来修改用户的名字。
更多方法: 类似地,我们定义了 changeSex 和 changeAge 方法,它们分别调用 changeUserSex 和 changeUserAge 方法来修改用户的性别和年龄。
得到一个结论:在兄弟组件中我们可以通过 Pinia 直接访问和修改 Store 中的状态,而不需要通过父组件再向子子进行中转通讯,这种方式简化了组件间的通信,使得组件更加独立。
最终效果:
但是我们发现,修改完数据后,我们刷新后数据又变回去了,怎么可以使这个数据修改后永久化不变呢,我们接着往下看:
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
const store=createPinia()
store.use(piniaPluginPersist)
createApp(App).use(store).mount('#app')
我们在main.js中引入pinia-plugin-persist
import {defineStore} from 'pinia'//是store的一部分
export const useUserStore=defineStore({
id:'user',
state:()=>{//数据源
return {
userInfo:{
name:'张三',
age:18,
sex:'boy'
}
}
},
actions:{//专门用来修改state
changeUserName(name){
this.userInfo.name=name
},
changeUserSex(sex){
this.userInfo.sex=sex
} ,
changeUserAge(n){
this.userInfo.age+=n
}
},
getters:{//仓库中的计算属性
afterAge(state){
return state.userInfo.age+10
}
},
persist:{//开启数据持久化
enabled:true,
strategies:[
{
path:['userInfo'],
Storage:localStorage
}
]
}
})
并且在user.js中加入一个persist对象,在里面把userInfo的数据永久化,我们再来看效果:
以看到数据被永久化了,大功告成。
总结
在本文中,我们深入探讨了如何使用 Pinia 来管理 Vue 应用的状态,并通过一个简单的例子展示了 Pinia 的基本用法。我们创建了一个用户信息管理应用,该应用能够展示用户的基本信息,并允许用户通过按钮来修改这些信息。
我们从安装 Pinia 开始,然后创建了一个 Pinia Store 来管理用户的状态。通过定义状态、动作和计算属性,我们实现了数据的存储、修改和计算。此外,我们还讨论了如何在 Vue 组件中使用这些状态和动作,以及如何利用 Pinia 的特性简化组件间的通信。