vue3使用pinia 实现权限code存取

简介: 在本文我们一开始了解了pinia是什么以及如果安装使用。接着结合使用pinia实现菜单权限控制的综合实例,来进一步了解pinia的使用。

前言

上一篇 vue3+element-plus权限控制实现(el-tree父子级不关联情况处理)
主要描述了权限控制综合实例中 el-tree 组件的使用细节。
这一篇,主要讲讲pinia 来存取权限code ,并且在 router.beforeEach 实现菜单的权限控制。


一、pinia 简要认识

Pinia 起始于 2019 年 11 月左右的一次实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库。

yarn add pinia
# 或者使用 npm
npm install pinia
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')

二、实现思路

登录后获取用户的权限code,用pinia存储起来,在路由守卫 router.beforeEach 取到code 然后过滤路由菜单。我这里的路由表是提前写好在前端的,主要结构如下图,其中关键的是meta 里面自定义的code,根据这个来判断是否拥有权限的。


  {
    path: '/pathXXX',
    name: 'pathXXX',
    meta: {
      keepAlive: true, //设置页面是否需要使用缓存
      title: 'pathXXX',
      icon: 'ShoppingCart',
      code: 'PermissionCode'  // 权限code
    },
    component: Layout,
    redirect: '/pathXXX/list',
    children: [
      {
        name: 'subPathXXX',
        path: '/subPathXXX',
        component: () => import('@/views/subPathXXX/index.vue'),
        meta: {
          keepAlive: true, 
          title: 'subPathXXX',
          icon: 'ShoppingCart',
          menuCode: 'subPermissionCode'
        }
      }
    ]
  },

三、详细实现步骤

1.用pinia 定义user store 用来存储用户相关的数据,安装 js-cookie 来辅助存在cookie里

import { defineStore } from 'pinia'
import Cookie from 'js-cookie'
import { getUserPermissonApi } from '@/api/xxx'
/**
 * @description 获取cookie
 * @param name
 * @returns value
 */
function getCookie(name: any) {
  return Cookie.get(name)
}
/**
 * @description 设置 cookie
 * @param name
 * @param value
 * @returns value
 */
function setCookie(name: any, value: any) {
  return Cookie.set(name, value)
}

// 你可以对 `defineStore()` 的返回值进行任意命名,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。(比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useUserInfoStore = defineStore('app-user', {
  state: () => ({
    menuPermission: getCookie('key') ? JSON.parse(getCookie('key') as any) : {}
  }),
  actions: {
    setUserPermisson(info: any) {
      this.menuPermission = info
      setCookie('key', this.menuPermission ? JSON.stringify(this.menuPermission) : '[]')
    },
    async getUserPermisson(params: {}) {
      try {
        const { data } = await getUserPermissonApi(params)
        this.setUserPermisson(data) // 这里就是获取code 对应上文 路由表结构中meta.code 来判断是否显示该菜单
      } catch (erro) {
        console.warn(erro)
      }
    }
  }
})

2. 在登录后获取用户的userId 与 token 后,调用定义好的 getUserPermisson 获取用户的权限code,并且存储起来

<script setup>
import { useUserInfoStore } from '@/store/modules/user'
const store = useUserInfoStore ()
const getUserPermissionCode = () => {
    // 获取了用户userid 等
    store.getUserPermisson({userid :xxx})
}
</script>

3. 在路由守卫 router.beforeEach 取到code 然后过滤路由菜单

import { start, done, configure } from 'nprogress'
// 提前写好路由表,主要meta.code 要对应上

let asyncRoutes: RouteRecordRaws[] = [
  {
    path: '/Pathxx',
    name: 'Pathxx',
    meta: {
      keepAlive: true,
      title: 'Pathxx',
      icon: 'x',
      code: '/Pathxx'
    },
    component: Layout,
    redirect: '/Pathxx',
    children: [
      {
        name: 'subPathXX',
        path: '/subPathXX',
        component: () => import('@/views/subPathXX/index.vue'),
        meta: {
          keepAlive: true, 
          title: 'subPathXX',
          icon: 'subPathXX',
          menuCode: 'subPathXX'
        }
      }
    ]
  },
]

configure({ showSpinner: false }) // NProgress 配置
const whiteList = ['/login']
router.beforeEach(async (to: RouteLocationNormalized, from: RouteLocationNormalized, next) => {
  start()

  const usePermission = usePermissionStore() //注意这个写在router.beforeEach 内部,写在外面有作用域问题

  const curToken = userStore.getToken
  if (curToken) {
    if (to.path === '/login') {
      next({ path: DefaultRoute })
      done()
    } else {
      try {
        const codeArr = usePermission.getMenuPermission || []
        const filterDynamicRoutes = (routes: any) => {
          for (let len = routes.length - 1; len >= 0; len--) {
            if (Array.isArray(codeArr) && codeArr.includes(routes[len].meta.menuCode)) {
              // 说明都有
              continue
            } else {
              if (routes[len].children && routes[len].children.length > 0) {
                filterDynamicRoutes(routes[len].children)
              } else {
                routes.splice(len, 1)
              }
            }
          }
        }
        filterDynamicRoutes(asyncRoutes)
      
        next(to.path)
      } catch (error) {
        next(`${import.meta.env.VITE_BASE_REDIRECT_TO}?redirect=${to.path}`)
        done()
      }
    }
  } else {
    if (whiteList.includes(to.path)) {
      next()
    } else {
      done()
    }
  }
})

总结

在本文我们一开始了解了pinia是什么以及如果安装使用。接着结合使用pinia实现菜单权限控制的综合实例,来进一步了解pinia的使用。

相关文章
|
1月前
|
JavaScript 前端开发 UED
vue2和vue3的响应式原理有何不同?
大家好,我是V哥。本文详细对比了Vue 2与Vue 3的响应式原理:Vue 2基于`Object.defineProperty()`,适合小型项目但存在性能瓶颈;Vue 3采用`Proxy`,大幅优化初始化、更新性能及内存占用,更高效稳定。此外,我建议前端开发者关注鸿蒙趋势,2025年将是国产化替代关键期,推荐《鸿蒙 HarmonyOS 开发之路》卷1助你入行。老项目用Vue 2?不妨升级到Vue 3,提升用户体验!关注V哥爱编程,全栈开发轻松上手。
|
1月前
|
JavaScript 前端开发 算法
高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图
mermaid是一款非常优秀的基于 JavaScript 的图表绘制工具,可渲染 Markdown 启发的文本定义以动态创建和修改图表。非常适合新手学习或者做一些弱交互且自定义要求不高的图表 除了流程图以外,mermaid还支持序列图、类图、状态图、实体关系图等图表可供探索。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
1月前
|
JavaScript 前端开发 API
你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解
onMounted作为vue3中最常用的钩子函数之一,能够灵活、随心应手的使用是每个Vue开发者的必修课,同时根据其不同写法的特性,来选择最合适最有利于维护的写法。博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
1月前
|
资源调度 JavaScript 前端开发
Pinia 如何在 Vue 3 项目中进行安装和配置?
Pinia 如何在 Vue 3 项目中进行安装和配置?
130 4
|
1月前
|
JavaScript 前端开发 API
管理数据必备;侦听器watch用法详解,vue2与vue3中watch的变化与差异
一篇文章同时搞定Vue2和Vue3的侦听器,是不是很棒?不要忘了Vue3中多了一个可选项watchEffect噢。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
5月前
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
178 58
|
5月前
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
152 56
|
3月前
|
资源调度 JavaScript 前端开发
创建vue3项目步骤以及安装第三方插件步骤【保姆级教程】
这是一篇关于创建Vue项目的详细指南,涵盖从环境搭建到项目部署的全过程。
444 1
|
4月前
|
JavaScript API 数据处理
vue3使用pinia中的actions,需要调用接口的话
通过上述步骤,您可以在Vue 3中使用Pinia和actions来管理状态并调用API接口。Pinia的简洁设计使得状态管理和异步操作更加直观和易于维护。无论是安装配置、创建Store还是在组件中使用Store,都能轻松实现高效的状态管理和数据处理。
238 3
|
9天前
|
JavaScript
vue实现任务周期cron表达式选择组件
vue实现任务周期cron表达式选择组件
59 4
下一篇
oss创建bucket