AddRoutes permission control

Scenario: Users who log in to the system may have different identities and permissions, and see different system menus and functions. In this case, dynamic routing is required

Routing structure: | – initRoutes default is can see routing, routing is all users can see menu | – asyncRouetes should confirm after landing permissions to see routing

1.1 Initial Route initRoutes

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:'login'
    },
    component:() = >import('.. /pages/login.vue')
},{
    path:'/home'.name:'home'.component:home,
    meta: {title:'home'}, {},path:'/news'.name:'news'.meta: {title:'news'
    },
    component:news
}]
export default new VueRouter({
    routes:allRoutes,
    mode:'hash'.//history
    base:'/'.True-router indicates that exact-active-link is added only when the route is a true match.
    // If there is only part overlap, active-menu is added.
    // fallback
    // Not all browsers support front-end routing. If not, set fallback: true.
    // Vue will automatically fallback to hash mode.
    fallback: true.linkActiveClass: "active-menu".linkExactActiveClass: "exact-active-menu",})// Inject the router instance into the vue root instance in main.js to use the route
Copy the code

1.2 Dynamic Routing asyncRouetes

var asyncRouetes = [
    {
        path:'/finance'.component:() = >import('.. /pages/finance.vue'),
        meta: {
            title: 'Financial Information'.roles: ['admin']}}, {path:'/staffs'.component:() = >import('.. /pages/staffs.vue'),
       meta: {
           title: 'Employee Information'.roles: ['admin'.'guest']}}];export default  asyncRouetes;
Copy the code

1.3 By default, only the initial route is passed in when vueRouters are instantiated

export default new VueRouter({
    routes:allRoutes,
    mode:'hash'.//history
    base:'/'.True-router indicates that exact-active-link is added only when the route is a true match.
    // If there is only part overlap, active-menu is added.
    // fallback
    // Not all browsers support front-end routing. If not, set fallback: true.
    // Vue will automatically fallback to hash mode.
    fallback: true.linkActiveClass: "active-menu".linkExactActiveClass: "exact-active-menu",})// Inject the router instance into the vue root instance in main.js to use the route
Copy the code
Mount at vUE instantiation timeCopy the code

1.4 Log in to obtain the token and user information

 localStorage.setItem('token'.'XXXXXXXXXXX');
 localStorage.setItem('userRole'.'admin'); //submain, guest
Copy the code

1.5 Adding a Global Route Guard

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';

// If it is global, no other pages need to be processed and the babel-plugin-component does not need to be configured
// 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();

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

{{msg}}

// // `, // components:{App}, // Register global components // template:' ' // }); import asyncRouetes from './router/dynamic.js'; var initRoutes = VueRouter.options.routes; / / optimization var allPaths = []; asyncRouetes.forEach((option) = >{ allPaths.push(option.path); }) VueRouter.beforeEach((to, from, next) = > { var userRole = localStorage.getItem('userRole'); var token = localStorage.getItem('token'); // Check whether dynamic routes have been added // Mode: Check whether the default route and the read route are the same var isHAS = VueRouter.options.routes.some((option) = >{ return allPaths.includes(option.path) }); if(isHAS){ next(); return; } // Check whether the token exists if(token && userRole){ var asyncRouete = asyncRouetes.filter((option,index) = >{ return option.meta.roles.includes(userRole); }); // Add the new route to the route. Cannot render correctly without a component VueRouter.addRoutes(asyncRouete); // To render the navigation correctly, add the corresponding new route to the VueRouter VueRouter.options.routes = [...initRoutes,...asyncRouete]; EventEmitter.$emit('allOption',VueRouter.options.routes) next(); } else { // Jump to the login page 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) / /]) // }, // Use the render function to render the component // render(h){ // return h(App) // }, render:h= >h(App) }); Copy the code

Second, the actual use of permission control in the project

2.1 Configuring necessary Dynamic routing Files

Add dynamy. js to the router folder. Add finance. Vue, staffs. Vue to the SRC /pages folder as a test

var asyncRouetes = [
    {
        path:'/finance'.component:() = >import('.. /pages/finance.vue'),
        meta: {
            title: 'Financial Information'.roles: ['admin']}}, {path:'/staffs'.component:() = >import('.. /pages/staffs.vue'),
       meta: {
           title: 'Employee Information'.roles: ['admin'.'guest']}}];export default  asyncRouetes;
Copy the code

2.2 ToEKN and user information need to be obtained after successful login

 localStorage.setItem('token'.'XXXXXXXXXXX');
 localStorage.setItem('userRole'.'admin'); //submain, guest
Copy the code

2.3 Perform navigation guard in entry file main.js

Import file:

 import asyncRouetes from './router/dynamic.js';
Copy the code

Global front-guard configuration:

Note: The route guard is for the vueRouter instance object

 VueRouter.beforeEach((to,from,next) = >{
     // if you have a custom title take the title, otherwise take the global title
   window.document.title = to.meta.title? to.meta.title:'Test system';

     // You can obtain the permission after login
     var UserToken = localStorage.getItem('token');
     var userRole = localStorage.getItem('userRole');

     // Check whether the token exists
     if(UserToken && userRole){
         / / have to log in
         var asyncRouteMenu = asyncRouetes.filter((item,index) = >{
             return item.meta.roles.includes(userRole)
         })

         // Add the new route to the route. Cannot render correctly without a component
         VueRouter.addRoutes(asyncRouteMenu); 
         // To render the navigation correctly, add the corresponding new route to the VueRouter
         
         var initRoutes = VueRouter.options.routes;
         VueRouter.options.routes = [...initRoutes,...asyncRouteMenu];
         next();

     } else {
         // Whether the login page is displayed
         if(to.path=='/login') {// Next ()
             next();
         } else {
             // Otherwise jump to login;
             next('/login'); }}})Copy the code

2.3 How to Display the menu

In app.vue, the original menu section

 <router-link to="/login" tag='li'> log in < / router - the link ><router-link to="/home? name=laney" tag='li'>The home page</router-link>
 <router-link to="/news" tag='li'>news</router-link> 
Copy the code

You need to change it to dynamic because all routes are not written to death and need to be retrieved from route instance this.$router.options

This can be set in the calculator property

<! DOCTYPE HTML > < HTML lang="en"> <head> <meta charset="UTF-8"> <title> 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"> <! -- write dynamic --> <! -- $router.options.routes can be added from the calculator property --> <! -- <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-view></router-view> </div> </template> <script> var Home={template:'<h3> I am Home </h3>'} var User={ Template :'#user'} var Login={template:'<h4> To obtain parameters: {{$route. The query}}, {{$route. The path}} < / h4 > '} var Regist = {template: '< h4 > user registration... Get parameters: {{$route. Params}}, {{$route. The path}} < / h4 > var Finance '} = {template: '< h4 > < / h4 >' financial information} var News = {template: '< / h3 > < h3 > I am a News'} Var initRoutes=[{path:'/home', Component: home, // Meta: {title: 'home'}}, {path:'/user', Component: user, meta: {title: 'users'}, / / the children: [/ / {/ / path:' login ', / / component: login / /}, / / {/ / path: ': regist / : username/password', / / component: Regist / /}} / /], / / {/ / path: '*', / / redirect: '/ home, / / hidden: true / / hide don't need to render the page on the routing / /}]; Var asyncRouetes = [{path:'/finance', component: finance, meta: {title: 'finance', roles: [' admin ']}}, {path: '/ news, component: news, meta: {title:' news center, roles: [' admin ', 'guest']}}]; Const routerAll=new VueRouter({routes:initRoutes, Equivalent to routes:routes linkActiveClass:'active', // Update active link class name, default active class linkExactActiveClass:'active-extact', // Precisely activated class mode: "hash", // default}); 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); }); Routerall. addRoutes(asyncRouete) cannot render routerAll.addRoutes(asyncRouete) correctly without adding a component; / / in order to correctly apply colours to a drawing navigation, add the corresponding new route to the routerAll routerAll. In the options. The 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'}); // Add route, switch route}, replace(){routerAll.replace({path:'user'}); // Replace route, no history}}}); </script> </body> </html>Copy the code

With the help of central control vUE instances, eventEmitter is utilized

  <template>
     <div id="app">
        <h1>{{msg}} <button type="button" @click="logOut()">The cancellation</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'> home </router-link> <router-link to="/news" tag='li'> news </router-link>
            </ul>
        <! - < ul @ click = "gotoPage ($event)" > < li tag = 'home "> home page < / li > < li tag =' news' > 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':
                        // This is equivalent to 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>
Copy the code