跳至主要內容

Vue3集成Pinia

sixkey大约 3 分钟前端Pinia

Vue3集成Pinia

可以存储token,同样用户登录后返回的个人信息也可存储

安装pinia

npm install pinia

在main.js中引入

import { createPinia } from 'pinia'
const pinia = createPinia()
//挂载到全局
app.use(pinia)

具体使用:以存储token为例

在项目中新建stores目录,其下新建token.js

import { defineStore } from "pinia";
import { ref } from "vue";

export const useTokenStore = defineStore('token',()=>{

    const token = ref('')

    const setToken = (newToken)=>{
        token.value = newToken;
    }

    const removeToken = ()=> {
        token.value = ''
    }

    return {
        token,setToken,removeToken
    }
});

在具体组件中使用:

在Login.vue中使用

用户登录成功后存储后台返回的token值

导入useTokenStore

import { useTokenStore} from '@/stores/token';
//解构出tokenStore
const tokenStore = useTokenStore();
//登录成功后存储token值
tokenStore.setToken(res.data.token);

这里有一个bug,当刷新浏览器后数据就不在了,这是因为pinia是基于内存存储,我们需要使用pinia的插件persist来进行持久化存储

安装persist

npm install pinia-persistedstate-plugin

在main.js中引入并在pinia中使用插件

import { createPersistedState } from 'pinia-persistedstate-plugin'

const pinia = createPinia()
const persist = createPersistedState()
pinia.use(persist)

修改token.js文件

添加一个对象值

import { defineStore } from "pinia";
import { ref } from "vue";

export const useTokenStore = defineStore('token',()=>{

    const token = ref('');

    const setToken = (newToken)=>{
        token.value = newToken;
    }

    const removeToken = ()=> {
        token.value = ''
    }

    return {
        token,setToken,removeToken
    }
},{
    persist: true //持久化存储
});

这里出现了一个小插曲,想在前置路由中通过判断token是否有值来进行路由跳转,原本是这样写的

import { createWebHistory, createRouter } from "vue-router";
import {LoginCheck} from '@/utils/loginCheck';
import { ElMessage } from "element-plus";
import { useTokenStore } from "@/stores/token";
//在这里就解构出对象,这种会报错说pinia是notActive的,就是没有被激活
const tokenStore = useTokenStore()

const history = createWebHistory();

const router = createRouter({
  history, // 路由模式
  routes: [
    {
      // 登录页面
      path: "/",
      name: "login",
      component: () => import("../views/Login.vue"),
    },
    {
      // 后台主页面
      path: "/home",
      name: "home",
      component: () => import("../components/home/Home.vue"),
      children: [
        {
          // 首页
          path: "/index",
          name: "index",
          component: () => import("../views/Index.vue"),
        },
        {
          // 用户管理
          path: "/user",
          name: "user",
          component: () => import("../views/user/User.vue"),
        },
        {
          // 公告管理
          path: "/notice",
          name: "notice",
          component: () => import("../views/notice/Notice.vue"),
        },
        {
          // 评价管理
          path: "/evaluation",
          name: "evaluation",
          component: () => import("../views/evaluation/Evaluation.vue"),
        },
        {
          // 反馈管理
          path: "/feedBack",
          name: "feedBack",
          component: () => import("../views/feedBack/FeedBack.vue"),
        },
        {
          // 部门管理
          path: "/department",
          name: "department",
          component: () => import("../views/department/Department.vue"),
        },
        {
          // 日志管理
          path: "/log",
          name: "log",
          component: () => import("../views/log/Log.vue"),
        },
        {
          // 会议管理
          path: "/reservation",
          name: "reservation",
          component: () => import("../views/reservation/Reservation.vue"),
        },
        {
          // 通知管理
          path: "/message",
          name: "message",
          component: () => import("../views/message/Message.vue"),
        },
        {
          // 签到管理
          path: "/sign",
          name: "sign",
          component: () => import("../views/sign/Sign.vue"),
        },
        {
          //会议室管理
          path: "/room",
          name: "room",
          component: () => import("../views/room/Room.vue"),
        },
      ],
    },
    { 
      path: "/:pathMatch(.*)*", 
      name: "NotFound", 
      component: () => import("../views/404/NotFound.vue")
    },
  ],
});
// GOOD
router.beforeEach((to, from, next) => {
  // const token = localStorage.getItem("token");
  if(to.name === 'login'){
    next()
  }else if(tokenStore.token){
    next()
  }else{
    ElMessage({
      showClose: true,
      message: "无权限,请重新登录!",
      type: "error",
    });
    next({
      name: 'login'
    })
  }
})
export default router;

改过之后是这样的

import { createWebHistory, createRouter } from "vue-router";
import {LoginCheck} from '@/utils/loginCheck';
import { ElMessage } from "element-plus";
import { useTokenStore } from "@/stores/token"; 

const history = createWebHistory();

const router = createRouter({
  history, // 路由模式
  routes: [
    {
      // 登录页面
      path: "/",
      name: "login",
      component: () => import("../views/Login.vue"),
    },
    {
      // 后台主页面
      path: "/home",
      name: "home",
      component: () => import("../components/home/Home.vue"),
      children: [
        {
          // 首页
          path: "/index",
          name: "index",
          component: () => import("../views/Index.vue"),
        },
        {
          // 用户管理
          path: "/user",
          name: "user",
          component: () => import("../views/user/User.vue"),
        },
        {
          // 公告管理
          path: "/notice",
          name: "notice",
          component: () => import("../views/notice/Notice.vue"),
        },
        {
          // 评价管理
          path: "/evaluation",
          name: "evaluation",
          component: () => import("../views/evaluation/Evaluation.vue"),
        },
        {
          // 反馈管理
          path: "/feedBack",
          name: "feedBack",
          component: () => import("../views/feedBack/FeedBack.vue"),
        },
        {
          // 部门管理
          path: "/department",
          name: "department",
          component: () => import("../views/department/Department.vue"),
        },
        {
          // 日志管理
          path: "/log",
          name: "log",
          component: () => import("../views/log/Log.vue"),
        },
        {
          // 会议管理
          path: "/reservation",
          name: "reservation",
          component: () => import("../views/reservation/Reservation.vue"),
        },
        {
          // 通知管理
          path: "/message",
          name: "message",
          component: () => import("../views/message/Message.vue"),
        },
        {
          // 签到管理
          path: "/sign",
          name: "sign",
          component: () => import("../views/sign/Sign.vue"),
        },
        {
          //会议室管理
          path: "/room",
          name: "room",
          component: () => import("../views/room/Room.vue"),
        },
      ],
    },
    { 
      path: "/:pathMatch(.*)*", 
      name: "NotFound", 
      component: () => import("../views/404/NotFound.vue")
    },
  ],
});
// GOOD
router.beforeEach((to, from, next) => {
  // const token = localStorage.getItem("token");
  //在前置路由中解构对象就对了
  const tokenStore = useTokenStore()
  if(to.name === 'login'){
    next()
  }else if(tokenStore.token){
    next()
  }else{
    ElMessage({
      showClose: true,
      message: "无权限,请重新登录!",
      type: "error",
    });
    next({
      name: 'login'
    })
  }
})
export default router;