Pinia:全新的Vue状态管理库,Vuex的代替者

特点:

  •  Vue2 和 Vue3 都能支持;
  • 抛弃传统的 `Mutation` ,只有 `state, getter` 和 `action(同步异步都支持)` ,简化状态管理库;
  • 不需要嵌套模块,符合 Vue3 的 Composition api,让代码扁平化;
  • TypeScript支持;
  • 代码简洁,透明、自动化的代码分割。

一、和vuex的区别

  • pinia只有 `state, getter` 和 `action(同步异步都支持)`;vuex的同步在`mutation`中完成,`action`处理异步;
  • pinia没有总出口,全是模块化,需要定义模块名称,当多个模块需要协作的时候,需要引入多个模块;vuex是有总出口的,当使用模块化的时候不需要引入多个模块;
  • pinia在修改数据的时候不需要通过其他api;vuex需要通过`commit`、`dispatch`。

二、基本使用

1.创建store

import { defineStore } from 'pinia';
export const mainStore = defineStore('main',{
    state:() => {
        return {
            msg:'Hello world!'
        }
    },
    getters:{},
    actions:{}
})

2.使用store

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

3.解构store

        当store中的多个参数需要被使用到的时候,更简洁的写法,通常采用解构的方式一次性获取所有的变量名。 

注意:ES传统方式解构(能获取到值,但是不具有响应性),如下:

  <script setup lang="ts">
  	import { mainStore } from '../store/index';
      const store = mainStore();
      const { msg } = store; // 这种写法,msg不会响应式更新。。。
  </script>
  <template>
      <h2>{{ msg }}</h2>
  </template>

Pinia解构方法:storeToRefs,如下:

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

三、修改数据状态

 1.简单修改

        直接在方法中通过 `store.属性名` 修改;

<script setup lang="ts">
	import { mainStore } from '../store/index';
    const store = mainStore();
    
    const addOne = () =>{
        store.count++;
    }
</script>
<template>
	<button @click="addOne">+1</button>
</template>

2.多条数据修改

        当修改多条数据时,pinia官方推荐使用 $patch ;该方法是经过优化的,会加快修改速度,对性能有很大好处。

 $patch方法可以接收两种类型的参数:函数和对象。

1)$patch  + 对象;

2)$patch  + 函数;

<script setup lang="ts">
	import { mainStore } from '../store/index';
    const store = mainStore();
    
    // $patch + 对象
    const onObjClick = () =>{
        store.$patch({
            msg: store.msg == 'Hello World' ? '111' : '222';
            count: store.count++;
        })
    };
    
    // $patch + 函数
    const onFuncClick = () =>{
        store.$patch((state)=>{
            state.msg = store.msg == 'Hello World' ? '111' : '222';
            state.count = store.count++;
        })
    }
</script>
<template>
	<button @click="onObjClick">click1</button>
	<button @click="onFuncClick">click2</button>
</template>

3.通过action修改

        在store.actions中添加修改数据的方法,在组件中通过 `store.方法名` 调用:

import { defineStore } from 'pinia';
export const mainStore = defineStore('main',{
    state:()=>{
		return{
            msg:'Hello world!',
            count:0
        }
    },
    getters:{},
    actions:{
        changeState(val){
            this.count = val;
            this.msg = "疫情快过去吧!"
        }
    }
})
<script setup lang="ts">
	import { mainStore } from '../store/index';
    const store = mainStore();
    
    const onClick = () =>{
        store.changeState(2);
    };
</script>
<template>
	<button @click="onClick">修改store中的状态</button>
</template>

四、getters

        pinia中的getter和vue中的计算属性几乎一样,在获取State值之前做一些逻辑处理。

        getter中的值有缓存特性,如果值没有变,多次使用也只会调用一次:

  import { defineStore } from 'pinia';
  export const mainStore = defineStore('main',{
      state:()=>{
          return{
              msg:'Hello world!'
          }
      },
      getters:{
          getCountBuff(state){
              console.log('getter被调用');
              return `${state.msg}***${state.msg}`;
          }
      }
  })
  <script setup lang="ts">
  	import { mainStore } from '../store/index';
      const store = mainStore();
  </script>
  <template>
  	<div>
          <h2>Getter 获取数据</h2>
          <div>{{ store.getCountBuff }}</div>
          <div>{{ store.getCountBuff }}</div>
          <div>{{ store.getCountBuff }}</div>
          <div>{{ store.getCountBuff }}</div>
      </div>
  </template>

        

        getter不仅可以通过传递 `state` 来获取到数据,还可以直接通过 `this` 来取到数据:

  getters:{
  	getMsgWithThis(): string{
      	return `${this.msg}***${this.msg}`;
      }
  }

五、store之间的相互调用

        在Pinia中,可以在一个 store1 中引入另一个 store2 ,然后通过调用 store2 的方法,获取到 store2 的状态。

// src/store/store2.js
import { defineStore } from 'pinia';
export const store2 = defineStore('movie',{
    state:()=>{
        return{
            movieList:['泰坦尼克号','绿皮书','肖申克的救赎','阿甘正传','星际穿越']
        }
    }
})
// src/store/store1.js
import { defineStore } from 'pinia';
import { store2 } from './store2';

export const store1 = defineStore('main',{
    state:()=>{
        return{
            msg:'Hello world!'
        }
    },
    getters:{
        getStore2():string[]{
    		return store2().movieList
		}
    }
})

六、开启持久化 persist

persist:{
    enabled:true,
    strategies:[]
}

七、vuex和pinia的优缺点

1.pinia优点:

  • 允许你在不重新加载页面的情况下修改store;
  • 为typescript设计的,提供了强类型支持,可以在开发中捕获更多的错误,提高代码的可维护性;
  • pinia提供devtool支持,有助于增强开发人员使用该工具的体验;
  • 摒弃了vuex中的mutation;
  • 无需再创建各个模块嵌套了,vuex中如果数据过多通常会分模块进行管理,而pinia中每个store都是独立的,互相不影响;
  • 体积非常小,只有1kb左右;
  • 支持插件来扩展自身功能;
  • 支持服务端渲染;
  • 兼容vue2和vue3;

2.pinia缺点:

  • 与vuex相比,它没有庞大的社区支持和解决方案;
  • 不支持调试功能,如时间旅行和编辑;

3.vuex优点:

  • 与pinia相比,它有庞大的社区支持和解决方案;

  • 支持调试功能,如时间旅行和编辑;

4.vuex缺点:

  • 它对typescript不友好;

  • 体积庞大,只适合大型SPA;

八、补充:时间旅行

参考文章

        在前端中,Vuex 借鉴 Flux 单向数据流思想,采用集中式统一管理保存状态。但是这些状态不会随时间改变而变化。为了使状态,可能被捕获、重播或重现,通过时间来回旅行。尤大开发了 vue-devtools 这样的工具,可以帮助我们的 Vue 应用可以实现这种时间旅行!

保证时间旅行的前提:

  • 单一的状态树`store`;
  • 只能通过`mutation`更改状态;

time travel:
    在vue-devtools的vuex状态面板中,有一个神奇的功能:`time travel`,
原理:
    所有的状态变更只能通过mutation,并且每次状态的改变都会产生一个全新的state对象,把每次变更的state对象事件都记录下来,展现出一个mutation列表,当你想展现什么时间段的状态,只需要切换到那个时间段的state对象。

每次产生新state的时候,需要对原state对象进行深拷贝,保证每次状态变更时原state不变,操作新的state。

九、总结 

    总得来说,Pinia 就是 Vuex 的替代版,可以更好的兼容 Vue2,Vue3以及TypeScript。在Vuex的基础上去掉了 Mutation,只保留了 state, getter和action。Pinia拥有更简洁的语法, 扁平化的代码编排,符合Vue3 的 Composition api。

  • 26
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3 中的 Pinia 和 Vue 2 中的 Vuex 是两种不同的状态管理,它们之间有一些区别。 1. API 设计:Pinia 在设计上更加简单和直观。它采用了类似于 Vue 3 的 Composition API 风格,通过创建独立的 store 实例并暴露出一组 getter、mutation、action 等函数来管理状态。而 VuexVue 2 中使用基于对象的 API,通过创建全局的 store 对象来管理状态。 2. 响应式系统:Pinia 使用了 Vue 3 的响应式系统,可以更好地与 Vue 3 的生态系统集成。它利用了 Proxy 对象来进行状态的跟踪和更新,提供了更高效和灵活的响应式能力。VuexVue 2 中使用了 Object.defineProperty 来实现响应式,与 Vue 2 的响应式系统紧密集成。 3. TypeScript 支持:Pinia 在设计上更加友好地支持 TypeScript。它提供了更强大的类型推导和类型约束,可以更好地帮助开发者在编写代码时避免错误。VuexVue 2 中也有一些 TypeScript 的支持,但相比之下 Pinia 提供了更好的类型支持。 4. 插件生态系统:由于 VuexVue 2 的官方状态管理,因此它有着非常丰富的插件生态系统。许多第三方插件和工具都与 Vuex 集成得非常好。Pinia 在 Vue 3 发布较短时间内,插件生态系统相对较小,但也在不断增长。 需要注意的是,虽然 Pinia 是 Vue 3 推荐的状态管理,但 Vuex 仍然可以在 Vue 3 中使用,并且在许多项目中仍然广泛使用。选择使用哪个状态管理取决于项目的需求、开发团队的经验和个人偏好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值