前端进阶--Vuex 与 Pinia 对比

为什么要使用pinia?

  • Vue2和Vue3都支持,这让我们同时使用Vue2和Vue3的小伙伴都能很快上手。
  • pinia中只有state、getter、action,抛弃了Vuex中的Mutation,Vuex中mutation一直都不太受小伙伴们的待见,pinia直接抛弃它了,这无疑减少了我们工作量。
  • pinia中action支持同步和异步,Vuex不支持
  • 良好的Typescript支持,毕竟我们Vue3都推荐使用TS来编写,这个时候使用pinia就非常合适了
  • 无需再创建各个模块嵌套了,Vuex中如果数据过多,我们通常分模块来进行管理,稍显麻烦,而pinia中每个store都是独立的,互相不影响。
  • 体积非常小,只有1KB左右。
  • pinia支持插件来扩展自身功能。

1、Vuex 与 Pinia 对比

  • Vuex 中核心部分: StateGettersMutations(同步) 和 Actions(异步)
  • Pinia 中核心部分: StateGettersActions(同步异步均支持)
  • pinia没有modules配置,没一个独立的仓库都是definStore生成出来的
  • pinia state是一个对象返回一个对象和组件的data是一样的语法

2、Pinia 在Vue3-Vite中的使用

Vue3 状态管理之 Pinia 的使用

一文搞懂pinia状态管理(保姆级教程) - 知乎 (zhihu.com)

① 创建一个vue vite项目

npm init vite@latest

② 安装 pinia

-S是为了将其保存至package.json中,便于Git管理给其他人的使用

npm install pinia -S

③ 创建 pinia 实例并挂载到 vue

// main.ts 文件
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
// 创建 Pinia 实例
const pinia = createPinia()
// 创建 Vue 实例
const app = createApp(App)
// 挂载到 Vue 根实例
app.use(pinia)
app.mount('#app')

④ 在src文件下创建一个store文件夹,并添加index.ts

// store/index.ts
import { defineStore } from 'pinia'
// 1. 定义容器、导出容器
// 参数1:容器的ID,必须是唯一的,后面Pinia会把所有的容器挂载到根容器
// 参数2:一些选项对象,也就是state、getter和action
// 返回值:一个函数,调用即可得到容器实例

export const useMainStore =  defineStore('main',{
    // 类似于Vue2组件中的data,用于存储全局状态数据,但有两个要求
    // 1. 必须是函数,目的是为了在服务端渲染的时候避免交叉请求导致的数据状态污染
    // 2. 必须是箭头函数,这样是为了更好的 TS 类型推导
    state:()=>{
        return {
            info:"pinia 可以使用",
            count:10
        }
    },
   // 类似于组件的computed,用来封装计算属性,具有缓存的功能
    getters:{
         // 函数接收一个可选参数:state状态对象
        count10(state){
            return state.count += 10
        },
        count10(state){
            return this.count += 10
        },
        // 若使用this.count,则必须指明返回数据的类型
        count11():number{
            return this.count += 11
        }
    },
    // 类似于vue2组件的methods,用于封装业务逻辑,修改state
// // 注意:不能使用箭头函数来定义actions,因为箭头函数绑定外部的this
    actions:{
        changeState (){
            this.count += 10
            this.info = "actions修改数据"
        },
        changeStates (num:number){
            this.count += num + 2
            this.info = "actions修改数据"
        }
    }
})

// 2. 使用容器中的 state
// 3. 通过 getter 修改 state 
// 4. 使用容器中的 action 同步和异步请求

⑤ 在组件中使用

<template>
  <h1>{{ mainStore.info}}</h1>
  <h1>{{ mainStore.count }}</h1>
  <h1>{{ mainStore.count10 }}</h1>
   <p>
        <button @click="alertData">修改数据</button>
   </p>
</template>

<script lang="ts" setup>
import { useMainStore } from "../store";
const mainStore = useMainStore();
import { toRefs } from 'vue'
// 解构数据,但是得到的数据是不具有响应式的,只是一次性的
// 相当于仅仅只是...mainStore而已,只是做了reactive处理,并没有做toRefs
// const { count, info } = useMainStore();
// 解决方法:
// 1. 通过使用toRefs函数,因为前面所说相当于是通过reactive处理,因此可以
// const { count, info } = toRefs(mainStore);
// 2. 通过pinia中提供的storeToRefs方法来解决,推荐使用

import { storeToRefs } from 'pinia'
const { count, info } = storeToRefs(mainStore);
const alertData = () => {
  // 方式一:最简单的方法,如下
  // 解构后更改方式
  // count.value += 10
  // 结构前更改方式
  // mainStore.count += 10
  // 方式二:若要同时修改多个数据,建议使用$patch来实现批量更新,在内部做了优化
  // mainStore.$patch({
  //   count: mainStore.count + 1,
  //   info: "hello"
  // })
  // 方式三:更好的批量更新方法,通过$patch传递一个函数来实现,这里的state就是useMainStore容器中的state
  mainStore.$patch(state => {
    state.count += 10
    state.info = "pinia批量更新"
  })
}

  // 方式四:通过 actions 来修改数据
  mainStore.changeState()
  mainStore.changeStates(10)
<style>
</style>

3、Pinia 数据持久化

  • 保存至localStorage中
  • 插件 pinia-plugin-persist 可以辅助实现数据持久化功能
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值