Pinia:非常好用的状态管理库
2024-08-12 14:30 阅读(264)

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 的特性简化组件间的通信。