跳至主要內容

8. Pinia

友人大约 6 分钟

8. Pinia

开始之前

在正式开始介绍 Pinia 之前,请先思考一下,你是否在日常开发中或者你的需求中遇到如下问题?

  • 不同 Vue 组件中的数据需要共享
  • 有些数据或方法需要全局访问

这样的需求该如何解决呢?答案是使用 Pinia

介绍

Pinia 是一个专门为 Vue 3 的专属状态管理库,它允许你跨组件或页面共享状态,提供了一种简单、直观和类型安全的方式来管理你的应用程序的状态。Pinia 的设计理念是结合了 Vue 3 的 组合式 API (Composition API) 和 TypeScript 的类型系统,以提供现代化和优雅的状态管理解决方案。

为什么不使用 Vuex 而使用 Pinia?

  1. Vuex 主要为 Vue2 设计的,而 Pinia 是基于 Vue3 的 组合式 API 风格设计,这使得在 Vue3 项目的开发时更灵活、更直观。

  2. Pinia 是使用 TypeScript 编写的,提供了很好的类型推断和类型安全,可以在编译时捕获到许多常见的类型错误,避免了在运行时出现一些难以调试的问题。

  3. Pinia 是基于 Vue3 的响应式系统构建的,而且会优化更新过程,只更新需要更新的部分,以提高性能和效率。

  4. Pina 提供了完善的异步操作支持,可以在 Action 中执行异步操作,并且能确保操作的正确执行顺序和结果。

  5. 最重要的一点,正如 Pinia 官网所述,Pinia 更加简单直观所见即所得所写即所得

安装

在使用 Pinia 之前,请先安装 Pinia。在项目的根目录下执行对应的如下指令,即可安装 Pinia

npm
npm install pinia

提示:如果你的应用使用的 Vue 版本低于 2.7,你还需要安装组合式 API 包:@vue/composition-api

使用

Pinia 存储数据是使用 store 来实现的,store 中的数据可以全局访问,以此来实现组件之间的数据共享问题。一般关于 Store 相关的内容将其放在 Vue 项目的 src/store/ 目录下。

Store是一个保存:状态业务逻辑 的实体,每个组件都可以读取写入它。

它有三个概念:stategetteraction,可以看做是组件中的: datacomputedmethods

如果你学过 Java,可以将其看做是一个公开的静态类,所有的属性和方法都是静态的。

存储数据

存储数据之前,需要先新建一个 store 文件,命名为 src/user.ts 来提供存储的位置,内容如下

// 引入 defineStore 用于创建 store
import { defineStore } from 'pinia'
import { reactive } from 'vue'

// 定义并暴露一个 store
export const useUserStore = defineStore('user',() => {
    // 这里演示的是 组合式 API 的写法
    let userInfo = reactive({
        uid : 1,
        username : 'codermast',
        nickname : '友人'
        url : "https://www.codermast.com/"
    });

    // 获取用户信息
    function getUserName() : string {
        // 将 username 转为大写
        return userInfo.value.username.toUpperCase();
    }

    // 需要手动进行返回暴露,这和 Vue3 中的 setup 有些差别
    return { userInfo, getUserName };
})

读取数据

将数据存储到 Store 中以后可以在 User.vue 这个组件中读取 User 信息。

在进行解构时,需要使用 storeToRefs ,和 Vue 中的 toRefs 类似,都是将数据转化为 ref 对象,方便在模板中使用。直接进行解构时,数据会失去响应式。

注意:pinia 提供的 storeToRefs 只会将数据做转换,而 Vue 的 toRefs 会转换 store 中所有的数据。推荐使用 storeToRefs。

  • 直接读取
<template>
    <h2>ID :{{ uid }}</h2>
    <h2>UserName :{{ username }}</h2>
    <h2>NickName :{{ nickname }}</h2>
    <h2>Url :{{ url }}</h2>
</template>

<script setup lang="ts">
    // 引入 useUserStore
    import { useUserStore } from '@/store/user'
    
    // 调用 useUserStore 得到对应的 store
    const userStore = useUserStore()

    // 从 userStore 中解构出 userInfo 对象
    let { userInfo } = userStore;
    // 从 userInfo 对象中解构出需要的属性
    // let { uid, username, nickname, url } = userInfo;
    let { uid, username, nickname, url } = storeToRefs(userInfo);
</script>
















 
 
 

  • getter 读取

除了直接读取数据以外,与 Vue 中的 计算属性 类似,可以对数据进行计算,然后返回。

定义 Getter

// 获取用户信息中的用户名
function getUsername() : string {
    return userInfo.username;
}

使用 Getter

// 引入 useUserStore
import { useUserStore } from '@/store/user'

// 调用 useUserStore 得到对应的 store
const userStore = useUserStore()

// 调用 Getter 方法
userStore.getUsername();    // codermast

修改数据

正如 Pinia 官网所说,Pinia 是符合直觉的 Vue 状态管理库,类型安全、可扩展性以及模块化设计。甚至让你忘记正在使用的是一个状态库。

Pinia 提供的所有数据,可以像 Vue 组件中原生定义的数据一样,可以直接修改。具体的修改有三种方式。

  1. 直接修改
// 调用 useUserStore 得到对应的 store
const userStore = useUserStore()

// 修改 username 
userStore.userInfo.username = "CoderMast"
  1. 批量修改
// 调用 useUserStore 得到对应的 store
const userStore = useUserStore()

// 1. 直接修改 username 
userStore.$patch({
    userInfo : {
        username : "CoderMast"
    }
})

// 2. 函数式修改 username
userStore.$patch((store) => {
    store.userInfo.username = 'CoderMast'
})

函数式修改时,会传一个 state 的参数,这个参数是 store 的内部状态,可以随意命名,只要与使用时保持一致即可。

  1. 借助action修改

在组合式 API 风格中,action 即就是 Mathod 方法,可以在方法中编写对应的数据修改规则,从而通过调用这些方法来实现修改数据的效果。

  • 定义 Action : 在 store/user.tsuseUserStore 内部定义,具体写法请参考:修改数据
function setUserName(newUsername : string) : void {
    // 1. 直接修改
    userInfo.username = newUsername;

    // 2. 使用 $patch 修改
    $patch((state) => {
        state.userInfo.username = newUsername;
    })
}
  • 使用 Action : 在 User.vue 中调用,具体的写法可参考 读取数据
// 引入 useUserStore
import { useUserStore } from '@/store/user'

// 调用 useUserStore 得到对应的 store
const userStore = useUserStore()

// 调用 action 
userStore.setUsername("CoderMast")

部署

如果你想要在生产环境使用 Pinia,需要进行安装和配置。

  1. 安装 Pinia

参考本文的 安装 Pinia 章节 即可

  1. 注册 Pinia

修改 src/main.ts 配置文件

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

// 引入createPinia,用于创建pinia 
import { createPinia } from 'pinia'

// 创建pinia 
const pinia = createPinia()
const app = createApp(App)

/// 使用插件 
app.use(pinia)
app.mount('#app')



 
 





 
 

  1. 使用 Pinia

到此,Pinia 章节就算结束了,本章节的代码演示都以 组合式 API 风格为主,也推荐使用这种方法,如果您想学习选项式,可以参考 尚硅谷Vue3入门到实战,最新版vue3+TypeScript前端开发教程