Vue实现路由权限及按钮级权限

主要有动态路由添加,按钮级权限,无限菜单等功能,写的很简略

地址:https://www.aliyundrive.com/s/ZDPUMQPhjc5

安装下依赖(yarn 或 npm i),直接yarn dev  或者  npm run dev 即可运行

分了两个角色,adminvip

首先我自己模拟的后台json数据

这个是管理员的,有子菜单的就不写component

let userInfo = {
    name: '坤坤',
    token: 'token XXX',
    role: 'admin',
    menu: [
        {
            path: '/about',
            name: 'about',
            children: [
                {
                    path: '/dance',
                    name: 'dance',
                    component: 'Dance'
                },
                {
                    path: '/rap',
                    name: 'rap',
                    children: [
                        {
                            path: '/basketball',
                            name: 'basketball',
                            children: [
                                {
                                    path: '/weiweiwei',
                                    name: 'weiweiwei',
                                    component: 'Test'
                                },
                                {
                                    path: '/weiweiwei2',
                                    name: 'weiweiwei2',
                                    component: 'Test'
                                },
                            ]
                        }
                    ]
                }
            ]
        },
        {
            path: '/sing',
            name: 'sing',
            component: 'Sing'
        }
    ]
}

export default userInfo

这个是vip的,有子菜单的就不写component

 let userInfo = {
    name: '张三',
    token: 'token XXX',
    role: 'vip',
    menu: [
        {
            path: '/about',
            name: 'about',
            component: 'About'
        },
        {
            path: '/sing',
            name: 'sing',
            component: 'Sing'
        }
    ]
}

export default userInfo

路由配置(配置了共有的页面,所有的动态路由,都添加到home的children里面)

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView,
      redirect: '/sing',
      children: [
        {
          path: '/sing',
          name: 'sing',
          component: () => import('../views/Sing.vue')
        }
      ]
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('../views/Login.vue')
    },
    {
      path: '/:pathMatch(.*)',
      name: 'notfound',
      component: () => import('../views/NotFound/index.vue')
    }
  ]
})

// 处理菜单,一会动态添加路由用
function getMenu(menu) {
  let newMenu = menu?.map(item => {
    return {
      path: item.path,
      name: item.name,
      component: item.component ? () => import(`../views/${item.component}.vue`) : '',
      children: getMenu(item.children)
    }
  })
  return newMenu
}
let newMenu = getMenu(JSON.parse(localStorage.getItem('userInfo'))?.menu)
newMenu?.forEach(item => {
  router.addRoute('home', item)
})

router.beforeEach((to, from, next) => {
  if (to.path === '/login') {
    next()
  } else {
    let token = localStorage.getItem('token')
    if (!token) {
      next('/login')
    } else {
      // 只有从login页面过来的,才执行下面操作(不然每次路由跳转都执行,不太好)
      if (from.path === '/login') {
        // 从本地拿数据,并动态添加到路由上
        let newMenu = getMenu(JSON.parse(localStorage.getItem('userInfo'))?.menu)
        newMenu?.forEach(item => {
          router.addRoute('home', item)
        })
      }
      next()
    }
  }
})

export default router

登录页(把个人信息和token全存到本地中)

<template>
  <div class="login">
    <el-form :model="form" label-width="60px">
    <el-form-item label="用户名">
      <el-input v-model="form.name" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">登录</el-button>
    </el-form-item>
  </el-form>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
import kunkun from '../data/kunkun'
import zhangsan from '../data/zhangsan'
import { useRouter } from 'vue-router'

const userouter = useRouter()

const form = reactive({
  name: '',
})

const onSubmit = () => {
  if (form.name === '坤坤') {
    localStorage.setItem('userInfo',JSON.stringify(kunkun))
    localStorage.setItem('token',kunkun.token)
    userouter.push('/')
  }
  if (form.name === '张三') {
    localStorage.setItem('userInfo',JSON.stringify(zhangsan))
    localStorage.setItem('token',zhangsan.token)
    userouter.push('/')
  }
}
</script>

<style lang="scss" scoped>
.login {
  width: 300px;
  height: 100px;
  background-color: pink;
  margin: 10px auto;
}
</style>

首页(向循环组件传递路由数据)

<template>
  <div class="common-layout">
    <el-container>
      <el-aside width="200px">
        <MenuTree :MenuData="MenuData"></MenuTree>
      </el-aside>
      <el-container>
        <el-header>
          <span>Header</span>
          <div>
            <span>{
   
   { uname }} --- {
   
   { role }}</span>
            <el-button @click="goback">退出</el-button>
          </div>
        </el-header>
        <el-main><RouterView /></el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script setup>
import { useRouter } from "vue-router";
import MenuTree from "../components/MenuTree.vue";

const userouter = useRouter();

let MenuData = JSON.parse(localStorage.getItem("userInfo"))?.menu;

let uname = JSON.parse(localStorage.getItem("userInfo"))?.name;
let role = JSON.parse(localStorage.getItem("userInfo"))?.role;

const goback = () => {
  localStorage.clear();
  userouter.replace("/login");
};
</script>

<style scoped lang="scss">
.el-aside {
  height: 100vh;
  background-color: pink;
}

.el-header {
  display: flex;
  justify-content: space-between;
  background-color: skyblue;
}
</style>

无限菜单组件(如果有children,就把数据传输,再调用自身)

<template>
  <el-menu
    :default-active="useroute.fullPath"
    v-for="item in MenuData"
    :key="item.path"
    router
  >
    <el-menu-item :index="item.path" v-if="!item.children">
      <span>{
   
   { item.name }}</span>
    </el-menu-item>
    <el-sub-menu :index="item.path" v-else>
        <template #title>
          <span>{
   
   { item.name }}</span>
        </template>
        <MenuTree :MenuData="item?.children" />
      </el-sub-menu>
  </el-menu>
</template>

<script setup>
import { defineProps } from "vue";
import { useRoute } from "vue-router";

const useroute = useRoute();

let { MenuData } = defineProps({
  MenuData: {
    default: [],
    type: Array,
    required: true,
  },
})
</script>
  

首页展示的二级菜单(根据角色渲染标签,就实现按钮级的权限)

<template>
  <h2>sing</h2>
  <el-button v-if="role === 'vip'">vip才显示</el-button>
  <el-button v-if="role === 'admin'">admin才显示</el-button>
</template>
  
<script setup>
let role = JSON.parse(localStorage.getItem('userInfo'))?.role
</script>
  
<style scoped>
</style>

猜你喜欢

转载自blog.csdn.net/qq_52845451/article/details/130218149
今日推荐