经验分享
2023了,你还不会Pinia吗?淦他!
# 前言时间过得真快,距离 `Vue3` 发布已经 `快三年` 了,相信很多开发 `Vue2` 的小伙伴,都使用过 `Vuex` 这个依赖,它可以帮我们管理项目中的所有 `数据`,我称它为 `数据
2023-04-20 22:34:29
7

前言

时间过得真快,距离 Vue3 发布已经 快三年 了,相信很多开发 Vue2 的小伙伴,都使用过 Vuex 这个依赖,它可以帮我们管理项目中的所有 数据,我称它为 数据仓库,在 Vue3 时代,我们潜规则式的摒弃了 Vuex,转而替代的是 Pinia,至于为什么使用它,我们稍后来谈。

介绍

正如前言所说,在 Vue3 时代,我们使用 Pinia 作为我们的数据仓库,是因为 Vue3 建议我们使用 Composition API 代替之前的 Options API,而 Pinia 与之完美的融合

  1. 使用 pinia作为数据仓库,可以很方便的在多个 组件/页面 中共用同一个变量
  2. TypeScript 的支持更加友好
  3. 可以在不重载页面的前提下修改仓库数据,且能实时响应在页面

与Vuex对比

  1. 抛弃了 mutations 的操作
  2. TypeScript 的支持更加友好
  3. 抛弃了 modulestore 目录下的所有 .ts/.js 文件均是一个 pinia 模块
  4. 自动导入注册

你可以查看这里,官方对 piniavuex 的对比:

image.pngimage.png

如何使用

安装引入

要想使用 pinia, 首先需要安装对应依赖:

npm i pinia

然后在 main.js 中引入并使用

// main.js中引入
// ...
const app = createApp(App);
 
// vue使用pinia
import { createPinia } from "pinia"
app.use(createPinia());

定义store

src/store 目录下新建 .js/.ts 文件,一个文件即是一个 store,通过 defineStore 来定义仓库

  1. 第一个参数为一个 唯一标识
  2. 第二个参数为一个 optionoption 中有 state、getters、actions 三个字段,分别表示 指代这个仓库的 数据、计算属性、方法
import { defineStore } from 'pinia';
 
export const demoStore = defineStore('demo', {
  state: () => {
    return {
      // 所有这些属性都将自动推断其类型
      counter: 0,
      mobile:"13111111111"
    }
  },
  getters:{},
  actions:{}
})

渲染state

接下来我们在 页面 渲染 state

<script setup>
// 引入定义的store
import { demoStore } from '@/store/demo';

const store = demoStore();
</script>

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

如果我们想直接渲染 counter 可以通过 storeToRefs 处理一下:

<script setup>
// 引入定义的store
import { demoStore } from '@/store/demo';
// 引入storeToRefs函数,使得解构store仍具有响应式特性
import { storeToRefs } from "pinia";

const store = demoStore();
const { counter } = storeToRefs(store);
</script>

<template>
<div>{{ counter }}</div>
</template>

修改state

修改 state 有四种方式,这里挨个来介绍一番:

方法一:直接修改

通过点击事件触发该 add 方法,直接操作 store.counter

const add = () => store.counter ++

方法二:$patch传递参数

通过点击事件触发该 add方法,通过 store.$patch 进行修改,参数是个 对象

const add = () => {
  store.$patch({
    count:store.counter + 2,
  })
};

方法三:$patch传递方法

通过点击事件触发该 add方法,通过 store.$patch 进行修改,参数是个 回调函数,可以在回调函数中处理

const add = () => {
 store.$patch(state => {
   state.counter += 10
 })
};

方法四:actions

src/store/demo.ts 文件中的 actions 中定义 add 方法:

import { defineStore } from 'pinia';
 
export const demoStore = defineStore('demo', {
  state: () => {
    return {
      // 所有这些属性都将自动推断其类型
      counter: 0,
    }
  },
  getters:{},
  actions:{
    add(n){
      this.counter = n;
    },
  }
})

在页面中通过调用 store.add 方法来修改:

const add = () => store.add(10)

Getters的使用

gettersvue 中的 computed 类似,提供计算属性:

// store/demo.ts
// ...
export const demoStore = defineStore('demo', {
  state: () => {
    return {
      mobile:"13111111111"
    }
  },
  getters:{
    mobileHidden:(state) => {
      return state.mobile.replace(/(\d{3})\d{4}(\d{4})/g,`$1****$2`);
    }
  },
  actions:{}
})

在页面中使用同 state

store互调

假设我们有多个 store,他们之间也是可以互相调用的,需要先将 testStore 调用实例化,然后读取里面方法:

// store/demo.ts
 
import { defineStore } from 'pinia';
// 引入第二个store
import { testStore } from './test';
 
export const demoStore = defineStore('demo', {
  state: () => {
    return {}
  },
  getters:{},
  actions:{
    getList(){
      const store2 = testStore();
      console.log(store2.fn())
    }
  }
})

结语

我是一名前端程序员,但不止于前端,如果有大佬觉得文章哪里有些欠妥,欢迎评论区一起讨论,一起学习~,最后,再次感谢你能看到这里。