(精华2020年5月14日更新) vue实战篇 vue-router动态路由的实现权限控制

router.js

import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);

import home from '../pages/home.vue';
import news from '../pages/news.vue';

var allRoutes = [{
    path:'/login',
    name:'login',
    meta:{
        title:'登陆'
    },
    component:()=>import('../pages/login.vue')
},{
    path:'/home',
    name:'home',
    component:home,
    meta:{
        title:'首页'
    },
},{
    path:'/news',
    name:'news',
    meta:{
        title:'新闻'
    },
    component:news
}]
export default new VueRouter({
    routes:allRoutes,
    mode:'hash', //history
    base:'/',
    //   vue-router 认为只有路由真正匹配时,才会加上 exact-active-link 这个 class,
    //   如果只有一部分重合,就会加上 active-menu。
    // fallback
    // 不是所有浏览器都支持前端路由的方式,如果不支持,设置 fallback: true,
    // vue 会自动 fallback 到 hash 模式。
    fallback: true,
    linkActiveClass: "active-menu",
    linkExactActiveClass: "exact-active-menu",
})
// 在main.js中把router 实例注入到 vue 根实例中,就可以使用路由了

权限路由

var asyncRouetes = [
    {
        path:'/finance',
        component:()=>import('../pages/finance.vue'),
        meta: {
            title: '财务信息',
            roles: ['admin']
        }
       },
       {
       path:'/staffs',
       component:()=>import('../pages/staffs.vue'),
       meta: {
           title: '员工信息',
           roles: ['admin','guest']
         }
       }
   ];

 export default  asyncRouetes;

在api.js

export default {
    basic:{
        login:'/api/login',
        info:'/api/info',
        msg:'/api/msg',
        hello:'/api/hello'

    },
    userInfo:{
        
    }
}

在main.js实现动态合并和权限控制

import Vue from 'vue';

import axios from './providers/axios2.js';
import api from './providers/api.js';

import App from './App.vue'
import VueRouter from './router/index.js';

//如果全局, 别的页面都不需要做任何处理, babel-plugin-component也不需要配置
// import ElementUI from 'element-ui';
// import 'element-ui/lib/theme-chalk/index.css';
// Vue.use(ElementUI);

Vue.prototype.$axios = axios;
Vue.prototype.$api = api;

window.EventEmitter = new Vue();

//template模式
// new Vue({
//     el:'#app',
//     data:{
//         hello:'hello',
//         msg:'world'
//     },
//     // template:`
// //

{{msg}}

// //
`,
// components:{App}, //注册全局组件 // template:'' // }); import asyncRouetes from './router/dynamic.js'; var initRoutes = VueRouter.options.routes; //优化 var allPaths = []; asyncRouetes.forEach((option)=>{ allPaths.push(option.path); }) VueRouter.beforeEach((to, from, next) => { var userRole = localStorage.getItem('userRole'); var token = localStorage.getItem('token'); //需要判断下是否已经添加过动态路由,不要重复添加 // 方式: 判断默认和路由和 读取的路由是否一致 var isHAS = VueRouter.options.routes.some((option)=>{ return allPaths.includes(option.path) }); if(isHAS){ next(); return; } //判断是否存在token if(token && userRole){ var asyncRouete = asyncRouetes.filter((option,index)=>{ return option.meta.roles.includes(userRole); }); //将新路由添加到路由中, 如果不加组件component不能正确渲染 VueRouter.addRoutes(asyncRouete); //为了正确渲染导航,将对应的新的路由添加到VueRouter中 VueRouter.options.routes = [...initRoutes,...asyncRouete]; EventEmitter.$emit('allOption',VueRouter.options.routes) next(); } else { // 跳转到登陆页面 if(to.path=='/login') { next(); } else { next('/login'); } } }) // render var vm = new Vue({ el:'#app', data:{ hello:'hello', msg:'world' }, router:VueRouter, // render(createElement){ // return createElement('div',{ // id:'app1' // },[ // createElement('h1',this.msg) // ]) // }, //使用组件,利用render函数渲染 // render(h){ // return h(App) // }, render:h=>h(App) });

app.vue

  <template>
     <div id="app">
        <h1>{{msg}} <button type="button" @click="logOut()">注销</button></h1>
        <div >
            <ul class="main-menu">
             <router-link v-for="(item,index) in getMyRoutes" :key="index" :to="item.path" tag='li'>{{item.meta.title}}</router-link> 
                <!-- <router-link to="/login" tag='li'>登陆</router-link> 
                <router-link to="/home?name=laney" tag='li'>主页</router-link>
                <router-link to="/news" tag='li'>新闻</router-link>  -->
            </ul>
        <!-- <ul @click="gotoPage($event)">
            <li tag='home'>主页</li>
            <li tag='news'>新闻</li>
        </ul>    -->
        </div>
        <router-view></router-view>
    </div>
</template>

 <script>
    export default {
        name: 'app',
        data () {
            return {
                msg: 'Welcome to ruanmou',
                getMyRoutes:[]
            }
        },
        computed:{
            // getMyRoutes(){
            //     console.log('this.$router.options.routes')
            //     console.log(this.$router.options.routes)
            //     var thisData = this.$router.options.routes;
            //     return thisData;
            // }
        },
        methods:{
             logOut(){
                localStorage.clear();
                this.$router.push({
                    path:'/login'
                })
                location.reload();
              },
            gotoPage(ev){
                var target = ev.target,
                    tag = target.getAttribute('tag');
                switch(tag){
                    case 'home':
                        //相当于get方式
                        this.$router.push({
                            path:'/home',
                            query:{
                                name:'laney'
                            }
                        })
                    break;
                    case 'news':
                        this.$router.push({
                            path:'/news',
                            query:{
                                age:'10'
                            }
                        })
                    break;
                }
                }
        },
        mounted(){  
            EventEmitter.$on('allOption',(res)=>{
                console.log('mounted')
                console.log(res)
                this.getMyRoutes = res;
            })
            console.log(this.$router.options.routes)
        }
    }
</script>

<style scoped>
.main-menu li {
    display: inline-block;
    margin-right: 30px;
    background: #000;
    color: #fff;
    padding: 5px 20px;
    cursor: pointer;
}
.main-menu li.active-menu{
    background: #ff6600;
    
}
</style>

附录html参考(计算属性实现路由过滤)

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>权限控制- addRoutes</title>
	<link rel="stylesheet" href="css/animate.css">
	<style>
		.active{
			font-size:20px;
			color:#ff7300;
			text-decoration:none;
		}
        .main-menu a {
            display: inline-block;
            margin-right: 10px;
        }
	</style>
	<script src="js/vue.js"></script>
	<script src="js/vue-router.js"></script>
</head>
<body>
	<div id="itapp">
		<div class="main-menu">
            <!-- 写成动态的 -->
            <!-- $router.options.routes  可以从计算器属性-->
            <!-- <router-link v-for="(item,index) in $router.options.routes" :key="index" :to="item.path">{{item.meta.title}}</router-link> -->
            <router-link v-for="(item,index) in getMyRoutes" :key="index" :to="item.path">{{item.meta.title}}</router-link>
            
        </div>
		<div>
			<transition enter-active-class="animated bounceInLeft" leave-active-class="animated bounceOutRight">
				<router-view></router-view>
			</transition>
		</div>

		<hr>
		<button @click="push">添加路由</button>
		<button @click="replace">替换路由</button>
	</div>

	<template id="user">
		<div>
			<h3>用户信息</h3>
			<ul>
				<router-link to="/user/login?name=tom&pwd=123" tag="li">用户登陆</router-link>
                <router-link to="/user/regist/alice/456" tag="li">用户注册</router-link>
			</ul>
			<router-view></router-view>
		</div>
    </template>

	<script>
		var Home={
			template:'

我是主页

'
} var User={ template:'#user' } var Login={ template:'

用户登陆。。。获取参数:{{$route.query}},{{$route.path}}

'
} var Regist={ template:'

用户注册。。。获取参数:{{$route.params}},{{$route.path}}

'
} var Finance={ template:'

财务信息

'
} var News={ template:'

我是新闻

'
} //默认是可以看到的路由 var initRoutes=[ { path:'/home', component:Home, // 路由元信息 meta: { title: '首页' } }, { path:'/user', component:User, meta: { title: '用户' }, // children:[ // { // path:'login', // component:Login // }, // { // path:'regist/:username/:password', // component:Regist // } // ] }, // { // path:'*', // redirect:'/home', // hidden: true //隐藏不需要渲染到页面上的路由 // } ]; //需要登陆后确认权限才能看到的路由 var asyncRouetes = [ { path:'/finance', component:Finance, meta: { title: '财务信息', roles: ['admin'] } }, { path:'/news', component:News, meta: { title: '新闻中心', roles: ['admin','guest'] } } ]; const routerAll=new VueRouter({ routes:initRoutes, //简写,相当于routes:routes linkActiveClass:'active', //更新活动链接的class类名,默认的激活的 class linkExactActiveClass:'active-extact', //精确激活的 class mode: "hash", //默认 }); ////导航守卫 //加入你获取了角色 routerAll.beforeEach((to, from, next) => { // var auth = localStorage.getItem('userRole'); var auth = 'admin'; var asyncRouete = asyncRouetes.filter((option,index)=>{ return option.meta.roles.includes(auth); }); //将新路由添加到路由中, 如果不加组件component不能正确渲染 routerAll.addRoutes(asyncRouete); //为了正确渲染导航,将对应的新的路由添加到routerAll中 routerAll.options.routes = [...initRoutes,...asyncRouete]; debugger next(); }) new Vue({ el:'#itapp', router:routerAll, //注入路由 computed:{ getMyRoutes(){ var thisData = this.$router.options.routes; return thisData; } }, methods:{ push(){ this.$router.push({path:'home'}); //添加路由,切换路由 }, replace(){ routerAll.replace({path:'user'}); //替换路由,没有历史记录 } } }); </script> </body> </html>

你可能感兴趣的:((持续更新)vue实战篇)