vue新一代状态管理插件Pinia

1、Pinia 的介绍

1.1、pinia 版本问题

Pinia是轻便化的全局状态管理器
中文网:pinia.web3doc.top/introductio…
源码:github.com/vuejs/pinia

  1. Vuex

Vuex当前最新版本是4.x,
Vuex4用于Vue3;
Vuex3用于Vue2

  1. Pinia

Pinia的最新版本是2.x,被认为是Vuex5。
对Vue2和Vue3做到很好的支持,也就是老项目也可以使用Pinia。

1.2、优点
  1. 支持Vue专用开发工具dev-tools

跟踪动作、突变的时间线
Store 出现在使用它们的组件中
time travel 和 更容易的调试

  1. 热模块更换

在不重新加载页面的情况下修改您的 Store
在开发时保持任何现有状态

  1. 支持扩展插件:使用插件扩展 Pinia 功能

如: 持久化工具 pinia-plugin-persist,可以非常方便地进行本地存储

  1. 更好的支持 TypeScript
  2. 支持服务器端渲染
1.3、pinia与 Vuex 的比较

与 Vuex 相比,Pinia 提供了一个更简单的 API,抛弃了Mutations的操作,具有更少的规范,提供了 Composition-API 风格的 API,与 TypeScript 一起使用时具备类型推断。

  1. Vuex有(state、mutations、actions、getters),

Action 提交的是 mutation,而不是直接变更状态。

const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})
//在vue页面中 
this.$store.dispatch("increment ")  //actions正常访问方式,需要用dispatch去触发actions对应的方法
  1. pinia有(state、actions、getters)

Action 可以包含同步与任意异步的操作。

2、Pinia的使用

2.1、安装与引入

安装

npm install pinia   //"pinia": "^2.0.13" 

项目中引入 Pinia 并创建容器挂载到根实例上
法一:

//main.js导入
import {createPinia} from 'pinia'          
createApp(App).use(createPinia()).mount('#app')  //createPinia()得加上括号

法二:

//main.ts中引入store根容器
import store from '@/store'
createApp(App).use(store).mount('#app')

//对应的store/index.ts中
import { createPinia } from 'pinia'
const store = createPinia()
export default store
2.2、Store的核心配置

作用:

Pinia和之前的Vuex一样,是 Vue 的存储库,允许跨组件/页面共享状态。

Store是保存状态与业务逻辑的实体,有三个核心概念

  1. state:存储全局状态
  2. getters:类似于组件的computed,根据已有state封装派生数据,也具有缓存的特性
  3. actions:类似于组件的methods,用来封装业务逻辑,支持同步和异步
2.3、重点函数介绍:
  1. createPina >> 见 2.1:安装与引用
  2. defineStore >> 声明一个Store
  3. storeToRefs
  4. $patch
  5. Action
  6. Getters
1)、defineStore定义容器

参数1:是对仓库的命名,名称必须具备唯一性;
参数2:是对容器仓库的配置,以对象的形式进行配置,

state 属性: 用来存储全局的状态的,这里边定义的,就可以是为SPA里全局的状态。
getters属性: 用来监视或者说是计算状态的变化的,有缓存的功能。
actions属性: 处理state里数据变化的业务逻辑。就是修改state全局状态数据。

import {defineStore} from "pinia";
export const useMainStore =  defineStore('main',{
  //必须是函数,为了避免在服务端交叉请求导致的状态数据污染,而且必须是箭头函数,为了更好的TS类型推导
  state:()=>{
      return{}
  },
  //用来封装计算属性 有缓存功能  类似于computed
  getters:{},
  //编写业务逻辑
  actions:{}
})
2)、storeToRefs()函数读取state

作用:
storeToRefs() 函数可将普通数据变成响应式数据,
且使用storeToRefs()将state中的状态解构出来,方便在视图中使用,

//相应的vue页面的script
import {storeToRefs} from 'pinia'    //先用import引入
const {count,name,arr,count10} = storeToRefs(mainStore)   //将mainStore容器的state值结构,并成为响应式数据
3)、$patch 函数修改多条 数据

修改state中多个数据时用 p a t c h , patch, patchpatch函数会批量更新,此时需要传入state参数;
这时候的state就是store仓库里的state,所以可以直接在函数里改变任何状态数据的值。
复制代码

//$patch加函数的形式修改状态数据
mainStore.$patch(state=>{      
          state.count++
          state.name += '~~'
          state.arr.push(5)
})

Pinia的官方网站,已经明确表示 p a t c h 的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。如果你是多条数据同时更新状态数据,推荐使用 patch的方式是经过优化的,会加快修改速度, 对程序的性能有很大的好处。如果你是多条数据同时更新状态数据,推荐使用 patch的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。如果你是多条数据同时更新状态数据,推荐使用patch方式更新。

4)、Action通过函数更改state

在store/index.js中添加changeState方法,在组件中用store调用

注:定义actions时不要使用箭头函数,因为箭头函数绑定外部this。使用容器中的state 时,action通过this操作;此外,还可以通过$patch修改state的数据

actions:{
changeState(num,str){
this.count += num //action通过this操作state的数据
this.name += str
this.arr.push(5)
this. p a t c h ( ) t h i s . patch({}) this. patch()this.patch(state=>{})
}
}
复制代码

5)、Getters

在store/index.js的Getters函数中添加count10()方法,在组件中用store调用,getters函数接收state参数
注:若组件中使用ts,getters使用this时,必须指定类型,否则会导致推导错误

getters:{
     count10(state){
      	 return state.count + 10
     }
     countOther():number{
         return this.count += 12
     }
},
2.4、总体代码演示

store/index.js文件

import {defineStore} from "pinia";
//参数1:定义一个仓库的唯一id名,Pinia会将所有的容器挂载到根容器;
//参数2:选项对象
export const useMainStore =  defineStore('main',{
//state必须是函数,一是避免在服务端渲染时的交叉请求导致的状态数据污染;二是为了更好的TS类型推导
  state:()=>{
    return{
      count:10,
      name:'wl',
      arr:[1,2,3],
    }
  },
   getters:{
       //函数接受一个可选参数:state
        count10(state){
            return state.count + 10
        }
        //在TS文件下,getters使用了this,则必须指定类型,否则会导致推导错误,(在定义常规函数时通过 this 访问到 整个 store 的实例)
        count10():number{   
            return this.count += 12
        }
   },
   //不要使用箭头函数定义action,因为箭头函数绑定外部this
   actions:{
         changeState(num,str){   
             this.count += num     
             this.name += str
             this.arr.push(5)          
         }
   }
})

Vue组件中的使用

<template>
  <h2>数量:{{mainStore.count}}---{{count}}</h2>
  <h2>姓名:{{mainStore.name}}---{{name}}</h2>
  <h2>arr:{{mainStore.arr}}---{{arr}}</h2>
  <h2>getter的使用:{{mainStore.count10}}---{{count10}}</h2>
  <button @click="changeNum">修改数量</button>
</template>
<script >
    import {useMainStore} from "./store/index.js"
    import {storeToRefs} from 'pinia'
    import {toRefs} from "vue";
    export default {
      name: 'App',
      setup(){
          const mainStore = useMainStore()
          const {count,name,arr,count10} = storeToRefs(mainStore)//使用storeToRefs函数将state里的数据解构出来实现响应式
          function changeNum() {
              mainStore.count++           	//法1
              mainStore.$patch({          	//法2:修改多个数据,用$patch
                  count:mainStore.count + 1,
                  name:mainStore.name + '!',
                  arr:[...mainStore.arr,4]
              })         
              mainStore.$patch(state=>{          //法3:$patch 加 函数的形式 批量更新
                  state.count++
                  state.name += '~~'
                  state.arr.push(5)
              })
              mainStore.changeState(10,'hello')   //法4:逻辑比较多时使用actions
          }
          return{count,name,arr,count10,mainStore,changeNum}
      }
    }
</script>

注意,state 和 $patch() 的直接更改都出现在 devtools 中

3、持久化工具 pinia-plugin-persist

Pinia与Vuex一样,刷新页面后,数据就会重置,有时候我们需要将数据进行持久化存储,我们可以使用pinia-plugin-persist这个插件
1). 安装:

npm i pinia-plugin-persist -D
pnpm install pinia-plugin-persist -D

2). main.ts引入store

//main.ts
import store from '@/store'
createApp(App).use(store ).mount('#app')

3). 在 store/index.ts 引入pinia-plugin-persist

import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist';
const store = createPinia()
store.use(piniaPluginPersist);   //将pinia-plugin-persist添加到 pinia 实例中
export default store

4). 在对应的modules中 写 需要持久化的 store 模块( config.ts)
添加 persist

import { defineStore } from 'pinia'
export const useConfigStore = defineStore({
  id: 'curTheme',
  state: () => {
    return {
      curTheme: 'light',
      name:'wl
    }
  },
  persist: {
      enabled: true,    // 开启缓存  默认会存储在本地localstorage
      strategies: [
          {
              key: 'key1',    // 修改存在缓存中的key值
              storage: localStorage,  /// 修改存储方式为localStorage,默认sessionStorage
              paths: ['curTheme']    // 只持久化'curTheme',此时刷新页面curTheme数据会被保留,其他state将会重置
          },
          {
              key:'key2',
              storage: localStorage,
              paths: ['curTheme','name']           
          }
          
      ]
  },
  getter:{
  },
  actions: {
    setCurTheme(data) {
      this.curTheme = data
    }
  }
})

注意:

pinia-plugin-persist要触发actions里的方法才会生效
一个store容器存储多条key,可在strategies里,设置多个对象,以key的不同名称区分,如代码中的key1,key2
如果一条key存储多个state的数据,可在paths数组里添加需要存储的名称,以,分割,如代码中key2的paths

5). 在vue页面中

//templete中
 <el-icon class="each_menu" :size="20" @click="changeCurTheme('dark')"   v-if="curTheme === 'light'" >
      <Sunny />
</el-icon>
<el-icon class="each_menu" :size="20" @click="changeCurTheme('light')"   v-else>
      <Moon  />
</el-icon>

//script中
import { ref, onMounted} from 'vue'
import { useConfigStore } from '@/store/modules/config.ts'
const configStore = useConfigStore()
const curTheme = ref(configStore.curTheme)
onMounted(() => {
  changeCurTheme(configStore.curTheme)
});
function changeCurTheme(themeName) {
    configStore.setCurTheme(themeName)    //使用action更改useConfigStore 中的curTheme值
    curTheme.value = themeName
    window.document.documentElement.setAttribute( "data-theme", themeName );
}

注:在浏览器的存储结果展示
在这里插入图片描述

4、总结

Pinia就是Vuex的替代产品,相比于Vuex,Pinia更好地兼容了Vue本身,代码更加简洁,开发起来也更加便捷。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值