一、什么是Pinia?

首先给出结论——Pinia是Vue专属的状态管理库。它和Vuex一样允许你跨组建或页面共享状态。

二、Pinia的优势。

既然Vuex和Pinia一样都是Vue状态管理库,那我们为什么还要学习Pinia呢?

这就要说到Pinia的优势了。

  • Pinia与Vuex不同,Pinia舍弃了Mutation,只有state,getter和action,简化了状态管理库。

  • Pinia的体积极小,只有1KB左右,几乎可以忽略不计。

  • Pinia不需要嵌套模块,符合Vue3的组合式Api。

  • PInia支持TypeScript,并且有很好的代码分割。

三、Pinia的基本使用。

1.安装

yarn add pinia
# 或者使用 npm
npm install pinia

2.创建Pinia的实例并应用。

import { createApp } from "vue";
import "./style.css";
import { createPinia } from "pinia";//引入
import App from "./App.vue";

const pinia = createPinia();//重新赋值
const app = createApp(App);

app.use(pinia);//使用
app.mount("#app");

3.state使用。

在src目录下新建一个store文件夹。并在store里新建user.ts文件(这里我用user.ts举例,实际情况根据业务有所不同)并初始化state,比如我们的用户信息有username,phone,email和age。

// src/store/user.ts
import { defineStore } from "pinia";
// defineStore的第一个参数是一个唯一标识(id),就跟我们每个人的身份证一样一样滴。
export const useUserStore = defineStore("users", {
  state: () => ({
    username: "张三",
    phone: "13333333333",
    email: "123456789@qq.com",
    age: 18,
  }),
});

使用也非常简单具体如下:

<template>
  <div>{{ userStore.username }}</div>
  <div>{{ username }}</div>
  <div>{{ age }}</div>
  <div>{{ email }}</div>
  <div>{{ phone }}</div>
  <button @click="setName">修改名字</button>
</template>

<script lang="ts" setup>
import { useUserStore } from "../store/user";//引入user
import { storeToRefs } from "pinia";
const userStore = useUserStore();
// const { username, age, email, phone } = userStore; //传统结构——不具有响应式
const { username, age, email, phone } = storeToRefs(userStore); //Pinia官方提供了storeToRefs()具有响应式
</script>

4.getter使用。

还是用user举例,getter的使用和Vue中的计算属性基本一致,都需要有返回值。具体如下

// src/store/user.ts
import { defineStore } from "pinia";
// defineStore的第一个参数是一个唯一标识(id),就跟我们每个人的身份证一样一样滴。
export const useUserStore = defineStore("users", {
  state: () => ({
    username: "张三",
    phone: "13333333333",
    email: "123456789@qq.com",
    age: 18,
  }),
  //getters和Vue中的计算属性基本一致,都需要有返回值
   getters: {
    //展示双倍年龄
    setAge: (state) => state.age * 2,
  },
});

当我们在store里定义好getter之后,就可以在组建中使用了。

<template>
  <div>实际年龄{{ age }}</div>
  <div>双倍年龄{{ setAge }}</div>
</template>
<script setup>
import { storeToRefs } from "pinia";
import { useUserStore } from "../store/user";
const userStore = useUserStore();
const { age, setAge } = storeToRefs(userStore);
</script>

5.action使用。

action的使用更偏向于业务了,我们在store里编写好actions,我这边写了一个修改手机号的方法作为举例。在actions里this的指向是当前的store,这一点要注意哦。

// src/store/user.ts
import { defineStore } from "pinia";
// defineStore的第一个参数是一个唯一标识(id),就跟我们每个人的身份证一样一样滴。
export const useUserStore = defineStore("users", {
  state: () => ({
    username: "张三",
    phone: "13333333333",
    email: "123456789@qq.com",
    age: 18,
  }),
  //getters和Vue中的计算属性基本一致,都需要有返回值
  getters: {
    //展示双倍年龄
    setAge: (state) => state.age * 2,
  },
    actions: {
    updatePhone(phoneNumber: string): void {
      console.log(this.phone);
      //actions里面的this指向store
      this.phone = phoneNumber;
      //这里可以写异步操作
      setTimeout(() => {
        console.log("异步操作", this.phone);
      }, 1500);
    },
  },
});

具体使用如下:

<template>
  <div>
    <button @click="setPhone">修改手机号</button>
  </div>
</template>
<script lang="ts" setup>
import { useUserStore } from "../store/user";
const userStore = useUserStore();
const setPhone = () => {
  userStore.updatePhone("19999999999");
};
</script>

控制台打印结果:

首先打印出初始化的电话号码,1.5s后打印出更改后的电话号码。

四、总结

Pinia作为Vuex的迭代产品,相比于Vuex有着更好的兼容性,对于熟悉Vuex的同学来说,上手还是比较简单的,这里我只展示了基本用法,感兴趣的同学可以在Pinia官方文档去学习更多细节。