Vue3中pinia使用及状态持久化存储

一、pinia基本使用

1.安装pinia

 npm install pinia

2.main.js注册

import { createPinia } from 'pinia'

app.use(createPinia())

3.定义store

  创建src/store/index.js

import { defineStore } from 'pinia'
export const useCommentStore = defineStore('comment', {
    // 静态数据
    state: () => {
        return {
            curCommentlist: []
        }
    },
    // 相当于计算属性(有数据缓存)
    getters: {
        getCurCommentlist(state) {
            return state.curCommentlist
        }
    },
    // actions即可以是同步函数也可以是异步函数
    actions: {
        changeCommentlist(curCommentlist) {
            this.curCommentlist = curCommentlist
        },
    }
})

4.页面使用

// 引入pinia仓库
import store from '../stores/index'
import { storeToRefs } from 'pinia'
const { useLoginStore, useCommentStore } = store
const commentStore = useCommentStore()
const curUsername = useLoginStore().getCurUsername // 无需赋值操作,getters计算属性获取即可
const { curCommentlist } = storeToRefs(commentStore) // 对状态进行赋值操作并保持响应式,不能使用getters

二、state修改方式

大致有如下四种修改state状态值的方式

// 引入pinia仓库
import { useLoginStore } from '../stores/loginStore.js'
import { storeToRefs } from 'pinia'
const loginStore = useLoginStore()
const { curUsername } = storeToRefs(loginStore)
const router = useRouter()
const formState = reactive({
    username: '',
    password: '',
    remember: true,
});
const onFinish = (values) => {
    const { username } = values
    // localStorage.setItem('username', username) // 改为如下pinia存储状态

    // pinia start
    // 方式一:最简单的方法,如下
    // 解构后更改方式
    curUsername.value = username;
    // 解构前更改方式
    // loginStore.curUsername = username;

    // 方式二:若要同时修改多个数据,建议使用$patch来实现批量更新,在内部做了优化
    // loginStore.$patch({
    //     curUsername: username
    // })

    // 方式三:更好的批量更新方法,通过$patch传递一个函数来实现,这里的state就是useLoginStore容器中的state
    // loginStore.$patch((state) => {
    //     state.curUsername = username
    // });

    // 方式四:通过 actions 来修改数据
    // loginStore.changeCurUsername(username);
    // pinia end

    router.push('/commentOn')
};

三、getters使用及注意事项

1.Getter 完全等同于 Store 状态的计算属性;Getters 函数的第一个参数是 state 对象

2.将参数传递给 getter (回调函数)

  Getter 只是幕后的计算属性,因此无法向它们传递任何参数。但是,您可以从 getter 返回一个函数来接受任何参数,请注意,执行此操作时,getter 不再缓存,它们只是您调用的函数。但是,您可以在 getter 本身内部缓存一些结果,这并不常见,但性能更高

import { defineStore } from 'pinia' // 导入 pinia 中的功能模块

// 创建容器
// 参数一:容器名
// 参数二:容器的内容
const useMainStore =  defineStore('main', {
  // pinia 状态管理的数据,通过箭头函数返回一个对象
  // 相当于 vue 中的 data 数据
  state: () => {
    return {
      count: 1,
    }
  },

  // 相当于 vue 中的 computed 计算属性
  getters: {
    // 定义的 getters,第一个参数就是该容器的 state
    comp(state) {
      return (num: number) => {
        return state.count + num
      }
    }
  },
})

// 导出容器
export {
  useMainStore
}

// 组件中使用

<template>
  <!-- 后面相同的调用,都是基于第一次计算的值 -->
  <p>{{ mainStore.comp(2) }}</p>
  <p>{{ mainStore.comp(3) }}</p>
  <p>{{ mainStore.comp(4) }}</p>
</template>

<script setup lang="ts">
// 导入 pinia 实例
import { useMainStore } from '../store/index'

// 实例化容器
const mainStore = useMainStore()
</script>

<style scoped></style>

3.getter中的this

  getter中同样可以使用 this,但是 TS 无法推导类型,需要手动指定返回值类型:

// 类似于组件的computed,用来封装计算属性,有缓存的功能
getters: {
  // 传入 state [可选参数]
  // computeds(state){
  //   console.log('getter运行了')
  //   return state.count + 1
  // }

  // !getter 中同样可以使用 this ,但是 TS 无法推导类型,需要手动指定返回值类型
  computeds():number {
    console.log('getter运行了')
    return this.count + 1
  }
},

4.访问其它getter

  与计算属性一样,您可以组合多个 getter。通过此访问任何其他 getter:

getters: {
  computeds():number{
    console.log('getter运行了')
    return this.count+2
  },

  double():number{
    this.foo = this.computeds * 2 
    return this.foo
  }
},

5.访问其它容器的actions 或getter

  直接导入并实例化容器后,使用即可,与前面的跨容器调用一致,不再展示示例代码

注意事项:

  1. 无更改state状态值操作,getters获取即可;需要更改state状态值,不能使用getters
  2. 组件视图需要更新,应该使用响应式api storeToRefs;视图无需依赖state更新直接用getters获取state即可
// pinia 获取列表
import { storeToRefs } from 'pinia'
import store from '../stores/index.js'
const { useLoginStore, useCommentStore } = store
const curUsername = useLoginStore().getCurUsername // 视图无需依赖更新使用getters获取即可
const commentStore = useCommentStore() 
const { curCommentlist } = storeToRefs(commentStore) // 页面视图更新需要使用响应式

四、pinia持久化存储

1.手动利用localStorage或sessionStorage进行存储

// 不使用pinia-plugin-persist进行持久化操作
// 通过 store 的 $subscribe() 方法查看状态及其变化;subscriptions 只会在 patches 之后触发一次
// useLoginStore().$subscribe((mutation, state) => {
//     // import { MutationType } from 'pinia'
//     mutation.type // 'direct' | 'patch object' | 'patch function'
//     // 与 loginStore.$id 相同
//     mutation.storeId // 'login'
//     // 仅适用于 mutation.type === 'patch object'
//     mutation.payload // 补丁对象传递给 to loginStore.$patch()
//     console.log('mutation', mutation);
//     // 每当它发生变化时,将整个状态持久化到本地存储
//     localStorage.setItem('login', JSON.stringify(state))
// })

// 1. 保存数据
const instance = useLoginStore();
instance.$subscribe((_, state) => {
    localStorage.setItem('login-store', JSON.stringify({ ...state }));
});
// 2. 获取保存的数据,先判断有无,无则用先前的
const old = localStorage.getItem('login-store');
if (old) {
    instance.$state = JSON.parse(old);
}

2.利用持久化工具 pinia-plugin-persist

  • 安装
npm i pinia-plugin-persist --save
  • main.js引入
// 引入pinia仓库
import { createPinia } from 'pinia'
// 持久化存储pinia
import piniaPluginPersist from 'pinia-plugin-persist'
const store = createPinia()
store.use(piniaPluginPersist)

const app = createApp(App)

app.use(store)
  • store中的配置参数 persist
import { defineStore } from 'pinia'

export const useLoginStore = defineStore('login', {
    // 静态数据
    state: () => {
        return {
            token: '',
            curUsername: '',
        }
    },
    persist: {
        enabled: true,
        // 自定义持久化参数
        strategies: [
            {
                // 自定义key
                key: 'login_store',
                // 自定义存储方式,默认sessionStorage
                storage: localStorage,
                // 指定要持久化的数据,默认所有 state 都会进行缓存,可以通过 paths 指定要持久化的字段,其他的则不会进行持久化。
                paths: ['curUsername'],
            }
        ]
    },
    // 相当于计算属性(有数据缓存)
    getters: {
        getCurUsername(state) {
            return state.curUsername
        },
    },
    // actions即可以是同步函数也可以是异步函数
    actions: {
        changeCurUsername(curUsername) {
            this.curUsername = curUsername
        },
    }
})

 

posted @ 2022-05-05 17:49  盼星星盼太阳  阅读(9385)  评论(1编辑  收藏  举报