Pinia入门 全新一代状态管理工具

224 阅读2分钟

简介

Pinia 是 vue 生态中 vuex 的替代者,自从 vue3.0 出来之后,Pinia 越来越受欢迎。可以同时支持 vue2.0 和 vue3.0,代码编写也变得十分简单,完整支持 ts。

环境与安装

虽然同时支持 vue2.0 和 3.0,但是我们现在直接使用 vue3.0 的环境,来安装 Pinia。

npm install pinia
//or
yarn add pinia

Pinia 的使用

  1. 需要在 main.ts 中引入 pinia
import { createPinia } from 'pinia'
import App from './App.vue'

//创建pinia
const pinia = createPinia();
const app = createPinia(App);
app.use(pinia);
......
  1. 使用 pinia 创建一个 store。首先我们在文件目录中创建个状态管理的文件夹 store,放在/src 下,专门用来管理相关状态。同时创建 index.ts 文件。
import { defineStore } from "pinia";

export const mainStore = defineStore("main", {
  state: () => {
    return {};
  },
  getter: {},
  actions: {},
});
//defineStore:  声明状态容器的名称main,名称唯一,不能重复;第二个参数是配置对象,里面含有配置相关内容。
//state:用来存储全局的状态,所有全局状态均在state里面定义。
//getter:类似于计算属性,可以计算状态变化,存在缓存
//actions:修改state中定义的状态数据
//下面会一一展开介绍
  1. 我们来为 state 添加一些全局状态的数据。
export const mainStore = defineStore("main", {
  state: () => {
    return {
      newState: "Hello World",
      count: 0,
      tel: 12345677890,
    };
  },
  getter: {},
  actions: {},
});

接下来我们在组件中调用:

<template>
  <div>{{ store.newState }}</div>
</template>

<script lang="ts" setup>
  import { mainStore } from "../store/index";
  const store = mainStore();
</script>

Pinia 改变状态的数据

修改状态数据,要比 vuex 简洁的多,比如我们定义一个记录点击次数的状态,count,每点击一次,count+1.

<template>
  <div @click="handleclick">{{ store.count }}</div>
</template>

<script lang="ts" setup>
import { mainStore } from "../store/index";
const store = mainStore();
const handleclick = () => {
  store.count++;
};
</script>

大家可能注意到了,为什么我没有采取解构的写法

<script lang="ts" setup>
const { count } = store;
</script>

这是因为,当你解构之后,解构的状态数据将不是响应式数据,当你修改 store 中的值之后,并不会及时发生变化。针对这个问题,pinia 提供了 storeToRefs()方法

import { storeToRefs } from "pinia";

这样就可以使用解构写法

<script lang="ts" setup>
const { count } = storeToRefs(store);
</script>

那么如何一次性修改多条数据呢?我们还用上文的 handleclick()方法,这时候我们用到了 pinia 的$patch

const handleclick = () => {
  store.$patch({
    count: store.count + 1,
    newState: `${store.newState} hello pinia!`,
  });
};

看到这里有没有觉得这样的代码很熟悉,既然可以传递对象,当然也可以传递一个函数。

const handleclick = () => {
  store.$patch((state) => {
    state.count++;
    state.newState = `${state.newState} hello pinia!`;
  });
};
// state 指的就是store对象

还记得上文中actions对象吗?既然解释了它是为了修改状态而存在的,那么为什么我们现在修改状态没用到呢?那是因为actions可以处理更为复杂的修改逻辑。

actions: {
  changeState(){
    this.count++;
    this.newState='hello pinia!'
  }
}

调用方式是这样的,依旧使用 handleclick()方法

const handleclick = () => {
  store.changeState();
};

Pinia 中的 getters

如果我们想在拿到值的时候,对值进行一些处理。我们可以在 getters 中实现。

//比如我们要把tel中间4位隐藏。
getters:{
  hideTel(state){
    return state.tel.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2')
  }
}

调用方法:

<template>
  <div>{{ hideTel }}</div>
</template>

<script lang="ts" setup>
import { mainStore } from "../store/index";
import { storeToRefs } from "pinia";
const store = mainStore();
const { hideTel } = storeToRefs(store);
</script>

getters 的缓存特性,就是当你在值没有变化的情况下 多次调用 hideTel(),实际只会调用一次,只有当tel的值发生改变的时候,才会再次调用。

Pinia 中 store 之间相互调用

我们在 store 文件夹下再创建个 index2.ts,作为另一个 store 容器,那么如何与 index.ts 的 store 之间相互调用呢?

//首先 我们需要引入index.ts
import { mainStore } from "./index.ts";

export const main2Store = defineStore("main2", {
  state: () => {
    return {
      newStore: "hello pinia",
      newCount: 0,
    };
  },
  getter: {},
  actions: {
    //这里我们写一个调用方法,就实现了相互调用。
    getCount() {
      console.log(mainStore.count);
      this.newCount = mainStore.count;
    },
  },
});

不足之处,多多指教。