• 【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由



    参考视频: VUE项目,VUE项目实战,vue后台管理系统,前端面试,前端面试项目

    案例链接
    【前端】Vue+Element UI案例:通用后台管理系统-导航栏(视频p1-16)https://blog.csdn.net/karshey/article/details/127640658
    【前端】Vue+Element UI案例:通用后台管理系统-Header+导航栏折叠(p17-19)https://blog.csdn.net/karshey/article/details/127652862
    【前端】Vue+Element UI案例:通用后台管理系统-Home组件:卡片、表格(p20-22)https://blog.csdn.net/karshey/article/details/127674643
    【前端】Vue+Element UI案例:通用后台管理系统-Echarts图表准备:axios封装、mock数据模拟实战(p23-25)https://blog.csdn.net/karshey/article/details/127735159
    【前端】Vue+Element UI案例:通用后台管理系统-Echarts图表:折线图、柱状图、饼状图(p27-30)https://blog.csdn.net/karshey/article/details/127737979
    【前端】Vue+Element UI案例:通用后台管理系统-面包屑、tag栏(p31-35)https://blog.csdn.net/karshey/article/details/127756733
    【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Form表单填写、Dialog对话框弹出(p36-38)https://blog.csdn.net/karshey/article/details/127787418
    【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Table表格增删查改、Pagination分页、搜索框(p39-42)https://blog.csdn.net/karshey/article/details/127777962
    【前端】Vue+Element UI案例:通用后台管理系统-登陆页面Login(p44)https://blog.csdn.net/karshey/article/details/127795302
    【前端】Vue+Element UI案例:通用后台管理系统-登陆页面功能:登录权限跳转、路由守卫、退出(p45-46)https://blog.csdn.net/karshey/article/details/127849502
    【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由(p47-48)https://blog.csdn.net/karshey/article/details/127865621
    【前端】Vue+Element UI案例:通用后台管理系统-项目总结https://blog.csdn.net/karshey/article/details/127867638

    目标

    • 不同用户登录后显示的菜单和能访问的页面不同
    • 动态添加路由

    代码

    0.动态地显示菜单:store

    菜单的显示在CommonAside.vue中,而不同用户登陆后会显示哪些菜单在permission.js里。因此,我们可以把permission.js里要显示的menu写在store中,CommonAside.vue只需要获取store的数据即可。

    在store的tab.js中:注意,要把菜单信息用cookie存起来,否则刷新后menu的信息就清空了。

    export default {
        state: {
            menu: [],//不同用户的菜单
        },
        mutations: {
            // 设置不同用户的菜单
            setMenu(state, val) {
                state.menu = val
                Cookie.set('menu', JSON.stringify(val))
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在Login.vue的submit函数中:在登录时commit

    submit() {
        // 表单的校验
        this.$refs.form.validate((valid) => {
            if (valid) {
                // 传入表单数据
                getMenu(this.login).then((data) => {
                    console.log(data);
                    if(data.data.code===20000){
                        // 记录cookie
                        Cookie.set('token',data.data.data.token)
                        // 设置菜单
                        this.$store.commit('setMenu',data.data.data.menu)
                        // 跳转到首页
                        this.$router.push('/home')
                    }else{
                        // 验证失败的弹窗
                        this.$message.error(data.data.data.message);
                    }
                })
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在CommonAside中显示菜单:在computed中

    // 获取菜单
    menuData() {
        return JSON.parse(cookie.get('menu')) || this.$store.state.tab.menu
    }
    
    • 1
    • 2
    • 3
    • 4

    效果:
    以用户

    username:xiaoxiao
    password:xiaoxiao
    
    • 1
    • 2

    登陆后,菜单发生了变化。
    在这里插入图片描述

    1.动态注册路由

    我们在以xiaoxiao登陆后,在url处访问user,结果是可以访问。
    原因是:我们在router处把路由写死了:

    const routes = [
        // 主路由
        {
            path: '/',
            component: Main,
            redirect: '/home', // 重定向
            children: [
                // 子路由
                { path: '/home', name: 'home', component: Home }, // 首页
                { path: '/user', name: 'user', component: User }, // 用户管理
                { path: '/mall', name: 'mall', component: Mall }, // 商品管理
                { path: '/page1', name: 'page1', component: PageOne }, // 页面1
                { path: '/page2', name: 'page2', component: PageTwo }, // 页面2
            ]
        },
        {
            path: '/login',
            name: 'login',
            component: Login
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    实际上,xiaoxiao只能访问“首页”和“商品管理”这两个路由。于是我们需要动态地添加路由。

    在store的mutation处:addMenu,动态地添加路由:

    // 动态添加路由
    addMenu(state, router) {
        // 判断Cookie
        if (!Cookie.get('menu')) return
        const menu = JSON.parse(Cookie.get('menu'))
        state.menu = menu
    
        const menuArray=[]
    
        // 组装路由
        menu.forEach(item => {
            // 判断是否有子路由
            if (item.children) {
                item.children = item.children.map(itemm => {
                    itemm.component = () => import(`../Views/${itemm.url}`)
                    return itemm
                })
                menuArray.push(...item.children)
            } else {
                item.component=()=>import(`../Views/${item.url}`)
                menuArray.push(item)
            }
        });
    
        menuArray.forEach(item=>{
            router.addRoute('Main',item)
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在Login处commit:

    // 动态添加路由
    this.$store.commit('addMenu',this.$router)
    
    • 1
    • 2

    注意要把router中写死的子路由注释掉。

    效果:在登录xiaoxiao时访问user是访问不了的。

    2.解决刷新后摆平问题

    我们在登录之后刷新页面,会白屏,原因是:我们只在Login登陆处添加了路由。而vue页面在刷新后会重新渲染,此时就没有路由的代码了。

    解决方法:在vue的created生命周期时就进行动态添加路由。

    new Vue({
      router,
      store,
      render: h => h(App),
      created() {
        store.commit('addMenu', router)
      }
    }).$mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    效果:刷新后也能显示页面了。

    总代码

    本篇修改的代码文件

    • CommonAside:显示菜单menuData,获取store的tab中的menu
    • router的index:注释掉子路由
    • store的tab:添加mutation的方法:设置菜单和动态添加路由;添加menu
    • Login:submit时commit在tab中新加的mutation方法
    • main.js:在created生命周期时就动态添加路由

    在这里插入图片描述

    tab.js

    import Cookie from "js-cookie"
    
    export default {
        state: {
            isCollapse: false,//导航栏是否折叠
            tabList: [
                {
                    path: '/',
                    name: 'home',
                    label: '首页',
                    icon: 's-home',
                    url: 'Home/Home'
                }
            ],//面包屑的数据:点了哪个路由,首页是一定有的
            menu: [],//不同用户的菜单
        },
        mutations: {
            // 修改导航栏展开和收起的方法
            CollapseMenu(state) {
                state.isCollapse = !state.isCollapse
            },
            // 更新面包屑的数据
            SelectMenu(state, item) {
                // 如果点击的不在面包屑数据中,则添加
                const index = state.tabList.findIndex(val => val.name === item.name)
                if (index === -1) {
                    state.tabList.push(item)
                }
            },
            // 删除tag:删除tabList中对应的item
            closeTag(state, item) {
                // 要删除的是state.tabList中的item
                const index = state.tabList.findIndex(val => val.name === item.name)
                state.tabList.splice(index, 1)
            },
            // 设置不同用户的菜单
            setMenu(state, val) {
                state.menu = val
                Cookie.set('menu', JSON.stringify(val))
            },
            // 动态添加路由
            addMenu(state, router) {
                // 判断Cookie
                if (!Cookie.get('menu')) return
                const menu = JSON.parse(Cookie.get('menu'))
                state.menu = menu
    
                const menuArray = []
    
                // 组装路由
                menu.forEach(item => {
                    // 判断是否有子路由
                    if (item.children) {
                        item.children = item.children.map(itemm => {
                            itemm.component = () => import(`../Views/${itemm.url}`)
                            return itemm
                        })
                        menuArray.push(...item.children)
                    } else {
                        item.component = () => import(`../Views/${item.url}`)
                        menuArray.push(item)
                    }
                });
    
                console.log(menuArray, 'menuArray');
    
                menuArray.forEach(item => {
                    router.addRoute('Main', item)
                })
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
  • 相关阅读:
    某30m小箱梁渠桥结构计算与施工图设计
    C++ Reference: Standard C++ Library reference: Containers
    资深Java工程师蚂蚁金服三面详解,看完你也可以拿offer
    一段时间后,stop-dfs.sh关不掉Hadoop3.1.3集群,stop-hbase.sh关不掉HBase集群
    node.js,vue-cli,webpack-cli安装教程(集合和完善别人的文章,解决了按照他文章出现的问题的解决方法,学生必备)
    java计算机毕业设计基于springboot人职匹配推荐系统
    Vue父子传值子组件接收的6种方式
    《永恒空间2》v1.1.36252中文版
    18.5.4 分布式恢复
    DayDayUp:计算机技术与软件专业技术资格证书之《系统集成项目管理工程师》课程讲解之十大知识领域之4辅助—项目人力资源管理
  • 原文地址:https://blog.csdn.net/karshey/article/details/127865621