likes
comments
collection
share

想学 pinia ?一文就够了有时候不得不承认,官方的总结有时就是最精简的,虽然作为Vuex的升级版,但为了尊重原作者,

作者站长头像
站长
· 阅读数 32

有时候不得不承认,官方的总结有时就是最精简的:

Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。

虽然作为Vuex的升级版,但为了尊重原作者,所以取名pinia,而没有取名Vuex,所以大家可以直接将pinia比作为Vue3的Vuex,同时,pinia提供了一种更简洁、更直观的方式来处理应用程序的状态,更为重要的是,pinia的学习成本更低,低到一篇文章就能涵盖pinia的全部。

Pinia的安装与配置:

首先自然是安装pinia,在基于Vue3的项目环境中,提供了npmyarn两种安装方式:

npm install pinia

yarn add pinia

随后,通常就是在src目录下新建一个专属的store文件夹,在其中的js文件中创建并抛出这个仓库。

import { createPinia } from 'pinia'  // 引入pinia模块

const store = createPinia()    // 创建一个仓库

export default store   // 抛出这个仓库

既然把这个仓库抛出了,那么现在便是让它能在全局起作用,于是在Vue的主要应用文件中(通常为main.js),引入使用pinia

import { createApp } from 'vue'
import App from './App3.vue'

import store from './store'  //引入这个仓库 

createApp(App).use(store).mount('#app')  // 再use一下

这样一来pinia仓库就能全局生效了!

Pinia的主要功能:

在官方文档中,Pinia提供了四种功能,分别是:

  1. Store:在Pinia中,每个状态管理模块都被称为一个Store。开发者需要创建一个Store实例来定义和管理状态。
  2. State:在Store中定义状态。可以使用defineState函数来定义一个状态,并通过state属性来访问它。
  3. Getters:类似于Vuex中的getters,用于从State中派生出一些状态。可以使用defineGetters函数来定义getters。
  4. Actions:在Pinia中,Actions用于处理异步操作或执行一些副作用。可以使用defineActions函数来定义Actions。

那么接下来我会通过一个具体的实例来表现出这四个功能,如下图:

想学 pinia ?一文就够了有时候不得不承认,官方的总结有时就是最精简的,虽然作为Vuex的升级版,但为了尊重原作者,

分别是充当仓库的Store功能。存储子组件User.vue中数据的State功能。另一个子组件Update-user.vue中,点击按钮后数据会实现更新,也就是修改State中数据的Actions功能。与无论点击多少次” 经过一年后按钮 ”,页面都会实现同步更新的Getters功能。

State:

简单来说,State的作用就是作为仓库的数据源。

就比如说,我想在仓库的数据源里面放上一个对象来进行使用,那我们只需在先前创建的store文件夹中再创建一个js文件,这里我给它起名为user,然后再其中这样添加对象。

(第一行引入的defineStore代表defineStorestore的一部分。)

import { defineStore } from 'pinia'   // defineStore 是 store 的一部分

export const useUserStore = defineStore({
    id: 'user',
    state: () => ({   // 仓库数据源
            userInfo: {
                name: '小明',
                age: 18,
                sex:'boy'
            }
    })
})

那么现在,我们想使用仓库中的数据就成为了一件非常容易的事。

正如上图,这里有一个父组件App.vue,两个子组件User.vueUpdate-user.vue

父组件不做任何动作,只包含对两个子组件的引用:

<template>
        <User/>
        <Updateuser/>
</template>

<script setup>
import User from './components/User.vue'
import Updateuser from './components/Update-user.vue'


</script>

<style lang="css" scoped>

</style>

子组件User.vue:

可以看到在这个子组件中,我们通过import { useUserStore } from '@/store/user'引用仓库,从而获得了仓库中小明姓名年龄性别的数据。

由于接下来的Update-user.vue组件中会添加几个按钮对这些数据进行修改,那么我们就要把这些数据设置成响应式。

正常情况下,store自带响应性,但如果我们不想每次都写userStore.userInfo.name这么长一大串,就可以尝试将这些值取出来赋给其他变量:

这里有两种方法,第一种是引入computed模块,如第14行年龄的修改。另一种是引入storeToRefs模块,这是一种属于Pinia仓库的模块,将整个userInfo变成响应式。

于是接下来,就轮到我们的Actions登场了

<template>
<ul>
    <li>姓名:{{ userStore.userInfo.name }}</li>
    <li>年龄:{{ age }}</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)   // 1. 计算属性使响应式能生效
const { userInfo } = storeToRefs(userStore)  // 2. 专门包裹仓库中函数用来返回对象

</script>

<style lang="scss" scoped>

</style>

Actions:

简单来说,Actions的作用就是专门用来修改State,如果你想要修改仓库中的响应式元素,只需要进行两步操作:

第一步:在user.js也就是我们的仓库中添加actions,专门设置函数用来修改state对象中的值。例如changeUserName作用是修改姓名, changeUserSex作用是修改性别。

import { defineStore } from 'pinia'   // defineStore  是 store的一部分

export const useUserStore = defineStore({
    id: 'user',
    state: () => ({   // 仓库数据源
            userInfo: {
                name: '小明',
                age: 18,
                sex:'boy'
            }
    }),
    actions: {                     // 专门用来修改state
        changeUserName(name) {
            this.userInfo.name = name
        },
        changeUserSex(sex){
            this.userInfo.sex = sex
        }
    }
})

子组件Update-user.vue:

第二步,在控制按钮的组件Update-user.vue中触发这两个函数,就如第10与14行的两个箭头函数。

<template>
   <button @click="changeName">修改仓库中用户姓名</button>
      <button @click="changeSex">修改仓库中用户性别</button>
</template>

<script setup>
import { useUserStore } from '@/store/user'  // 引入Pinia仓库
const userStore = useUserStore()            // 声明仓库

const changeName = () => {                  // 触发提供的函数
  userStore.changeUserName('小红')

}
const changeSex = () => {
  userStore.changeUserSex('gril')
}

</script>

<style lang="css" scoped>

</style>

想学 pinia ?一文就够了有时候不得不承认,官方的总结有时就是最精简的,虽然作为Vuex的升级版,但为了尊重原作者,

这样一来,依赖于Actions,我们就成功完成了响应式修改仓库中数据的功能,也就是前两个按钮的功能!

Getters:

简单来说Getters就是仓库中的计算属性。

现在我们来实现第三个按钮功能,首先就是在User.vue组件中第5行,添加 “ 十年之后年龄 ” 一栏:

<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>

那么现在你一定能注意到这一栏其中的userStore.afterAge,这正是我们将在getters中返回的值。

那么关于getters,具体的使用方法就是继续在user.js中添加进getters,我们在其中打造了一个afterAge函数来返回userStore.afterAge,正如第25行。

import { defineStore } from 'pinia'   // defineStore  是 store的一部分

export const useUserStore = defineStore({
    id: 'user',
    state: () => ({   // 仓库数据源
            userInfo: {
                name: '小明',
                age: 18,
                sex:'boy'
            }
    }),
    actions: { // 专门用来修改state
        changeUserName(name) {
            this.userInfo.name = name
        },
        changeUserSex(sex){
            this.userInfo.sex = sex
        },
        changeUserAge(age){           //  新添加的一年后年龄计算方法
            this.userInfo.age += age
        }
    },
    getters: { // 仓库中的计算属性,所依赖的值改变会重新执行
        afterAge(state) {
            return state.userInfo.age + 10
        }
    }
})

准备工作完毕,现在就该在页面上添加这个按钮,于是在组件Update-user.vue添加上按钮与执行函数。

 <button @click="changeAge">经过一年后</button>
const changeAge = () => {
  userStore.changeUserAge(1)
}

有了这些之后,这个项目的功能便彻底完善,无论点击多少次“ 经过一年后 ”按钮,在页面上显示的值都是正确且实时更新的,这就是Getters的功劳!

补充:数据持久化

关于整个项目的功能实现确实已经结束,但人的贪心却是不得满足的,如果我们想要在原有的基础上实现网页刷新数据却不刷新,也就是说数据的持久化,那又该怎么办呢?

想学 pinia ?一文就够了有时候不得不承认,官方的总结有时就是最精简的,虽然作为Vuex的升级版,但为了尊重原作者,

很简单,也就是堪堪三步,便能实现。

第一步:安装persist插件。

npm i pinia-plugin-persist

第二步:在storejs文件中引入这个插件。

import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'  //引入插件

const store = createPinia()
store.use(piniaPluginPersist)  // 使用插件

export default store

第三步:在我们前文user.jsdefineStore库内继续添加上persist功能。

persist: { // 持久化
    enabled: true,
    strategies: [ // 里面填想要持久化的数据
    {
        paths: ['userInfo'],    // 指明持久化的数据
        storage: localStorage  // 指明存储
    }
    ]
}

现在可以看到点击按钮后的数据都被存储到浏览器的存储空间中,无论多少次刷新都不会被重置!

想学 pinia ?一文就够了有时候不得不承认,官方的总结有时就是最精简的,虽然作为Vuex的升级版,但为了尊重原作者,

最后:

至此,这样一个简简单单的项目,却解释清楚了Pinia功能的核心,读完这篇文章,相信每一个学习Pinia的人都能有所收获。

转载自:https://juejin.cn/post/7407407711879807026
评论
请登录