使用 pinia-plugin-persist & 今天踩的坑 | 青训营笔记

4,542 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第7天。

昨天讲了一下 pinia 的使用,在很多时候需要我们去做一下持久化存储(比如以今天做的token存储为例,这里指的是存到 localStorage),当然可以使用localStorage.getItem("xxx")来做,不过这里使用pinia-plugin-persist这款插件就可以更加方便来做这个事情。

01 使用 pinia-plugin-persist

一、安装插件

 npm i pinia-plugin-persist --save

二、store/index.js

 import { createPinia } from 'pinia'
 import piniaPluginPersist from 'pinia-plugin-persist'
 ​
 const store = createPinia()
 store.use(piniaPluginPersist)
 ​
 export default store

三、store/user.js

 export const useUserStore = defineStore({
   id: 'user',
 ​
   state: () => {
     return {
       name: '张三'
     }
   },
   
   // 开启数据缓存
   persist: {
     enabled: true
   }
 })

四、自定义 key

数据默认存在 sessionStorage 里,并且会以 store 的 id 作为 key。

通过 key & storage 配置就可以指定 key 和存储的位置。

 persist: {
   enabled: true,
   strategies: [
     {
       key: 'my_user',
       storage: localStorage,
     }
   ]
 }

五、持久化局部 state

默认所有 state 都会进行缓存,其实能够通过 paths 指定要持久化的字段,其余的则不会进行持久化。

 state: () => {
   return {
     name: '张三',
     age: 18,
     gender: '男'
   }  
 },
 
 persist: {
   enabled: true,
   strategies: [
     {
       storage: localStorage,
       paths: ['name', 'age']
     }
   ]
 }

所以这里的 gender 将不会存储到 localStorage 。

02 踩坑【大意了】

看到这里相信已经会使用 pinia-plugin-persist 插件了。

但是今天我也是按照这个步骤一步步来,但是没有在 localStorage 看到。

下面是我的代码:

main.ts

 import { createApp } from "vue";
 ​
 import App from "./App.vue";
 import router from "./router";
 ​
 import "./assets/main.css";
 ​
 const app = createApp(App);
 ​
 app.use(router);
 ​
 app.mount("#app");
 ​

stores文件夹下的

index.ts

 import { createPinia } from "pinia";
 import piniaPluginPersist from "pinia-plugin-persist";
 ​
 const store = createPinia();
 store.use(piniaPluginPersist);
 ​
 export default store;
 ​

user.ts

 import { defineStore } from "pinia";
 ​
 export const useUserStore = defineStore({
   id: "user",
   state: () => {
     return {
       token: "",
     };
   },
   actions: {
     setToken(token: any) {
       this.token = token;
     },
   },
   // 开启数据缓存
   persist: {
     enabled: true,
     strategies: [
       {
         storage: localStorage,
         paths: ["token"],
       },
     ],
   },
 });
 ​

login.vue

<template>
	......
</template>

<script setup lang="ts">

......

// store
import { useUserStore } from "../stores/user";
const userStore = useUserStore();

......

//账号密码点击登录
const userBtnL = (formEl: any) => {
  if (!formEl) return;
  formEl.validate((valid: unknown, fields: unknown) => {
    if (valid) {
      login({
        username: ruleForm.username,
        password: Encrypt(ruleForm.userpwd),
      }).then((res: any) => {
        if (res.code != 1000) {
          ElMessage({message: res.message,type: "error",});
          return;
        }
        ElMessage({message: `${ruleForm.username}登陆成功!`,type: "success",});

        // 将 token 存到 userStore 里面
        userStore.setToken(res.data.access_token);
          
      });
    } else {
      console.log("error submit!", fields, valid);
    }
  });
};
</script>

<style scoped>......</style>

咋一看没什么问题。

而且我发现在 vue devtool 可以看到确实已经存到 token 里面了,但是没有在 localStorage 看到。

image.png


这个问题我卡住了很久,最终找到了原因。

原来是为了方便对其进行了分包,在 index.ts 文件 use pinia-plugin-persist 等插件,在 user.ts 就是关于用户的,在 post.ts 就是关于文章的 ...... 但是我忘记了一个最重要的,就是在main.ts 引入 stores 下的 index.ts 的 createPinia() !所以只要修改一下 main.ts 如下:

import { createApp } from "vue";

import App from "./App.vue";
import router from "./router";
// !!!不要忘记引入
import store from "./stores";

import "./assets/main.css";

const app = createApp(App);

app.use(router);
app.use(store);

app.mount("#app");



image.png


最后问题解决,主要是这种不报错的bug最难找了,所以打代码还是要细心一点!