通常我们在vue项目中都是前端配置好路由的,但在一些项目中我们可能会遇到权限控制,这样我们就涉及到动态路由的设置了,所以 这是我们需要用到我们的动态路由来解决问题

一、从接口获取菜单、路由

登录了,登录人的信息会传给后台,后台就会判断,这个登录的人是什么角色,这个角色有什么权限或者说路由、菜单数据。

这里采用的mock进行的后台数据的模拟

mock里面的数据格式

export default [
    { name:'Home',tilte: '首页', icon: 'el-icon-s-home', path: '/home' ,component:'Home'},
    { name:'Menu',tilte: '菜单管理', icon: 'el-icon-menu', path: '/menu' ,component:'Menu'},
    { name:'Department',tilte: '部门管理', icon: 'el-icon-s-help', path: '/department',component:'Department'},
    { name:'Role',tilte: '角色管理', icon: 'el-icon-user-solid', path: '/role' ,component:'Role'},
    { name:'Order',tilte: '订单管理', icon: 'el-icon-s-order', path: '/order' ,component:'Order'},
  ]

axios二次封装 

import axios from 'axios';

const _axios = axios.create({
    baseURL:'https://www.fastmock.site/mock/56fbd71662d3ff554b25859d7b965943/api'
});

// 添加请求拦截器
_axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
_axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

  export default _axios;
import _axios from '@/util/request.js'

export function getNavData(){
    return _axios({
        method:'get',
        url:'/menuList'
    })
}

二、动态添加菜单

<template>
  <div id="app">
    <div class="layout">
      <div class="leftMenu">
        <el-menu
          router
          :default-active="$route.path"
        >
          <el-menu-item
            v-for="(item,index) in lists"
            :index="item.path"
            :key="index"
          >
            <i :class="item.icon"></i>
            <span slot="title">{{item.tilte}}</span>
          </el-menu-item>
        </el-menu>
      </div>
      <div class="rightContent">
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script>
import { getNavData } from '@/api/index'
export default {
  name: 'app',
  components: {
  },
  mounted() {
    console.log(this.$route.path)
  },
  data() {
    return {
      lists: []
    }
  },
  mounted() {
    this.getMenuList();
  },
  methods: {
    getMenuList() {
      getNavData().then(res => {
        console.log(res);
        let { code, menuList } = res.data
        if (code == 200) {
          this.lists = menuList;
        }
      }).catch(err => {

      })
    }
  }

}
</script>

<style lang="scss">
* {
  padding: 0;
  margin: 0;
}
html,
body,
#app {
  width: 100vw;
  height: 100vh;
}
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  .layout {
    width: 100vw;
    height: 100vh;
    display: flex;
    .leftMenu {
      flex-basis: 200px;
    }
    .rightContent {
      flex: 1;
      background: wheat;
    }
  }
}
</style>

三、动态添加路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

import { getNavData } from '@/api/index'
Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'HomePage',
    redirect:'/home',
    component: Home
  }
]

const router = new VueRouter({
  linkActiveClass:'selected',
  routes
})

// 路由拦截,在url地址跳转之前执行
router.beforeEach((to,from,next)=>{
  addRoutes();
  next()
})

function addRoutes(){
  getNavData().then(res=>{
    console.log(res);
    let { code, menuList } = res.data;
    if(code ==200){
      // 拼接路由数据
      let data = routesData(menuList);
      router.addRoutes(data);
    }
  })
}

function routesData(menuList){
  menuList.forEach(item=>{
    routes.push({
      path:item.path,
      name:item.name,
      meta:{title:item.title},
      component:()=>import(`../views/content/${item.component}`)
    })
  })
  return routes;
}

export default router

四、数据缓存

使用vuex减少请求次数

配置vuex方法

mport Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    nav:[]
  },
  mutations: {
    setNav(state,nav){
      state.nav = nav
    }
  },
  actions: {
    SET_NAV({commit},nav){
      commit('setnav',nav);
    }
  },
  modules: {
  }
})

五、菜单从vuex获取数据

<template>
  <div id="app">
    <div class="layout">
      <div class="leftMenu">
        <el-menu
          router
          :default-active="$route.path"
        >
          <el-menu-item
            v-for="(item,index) in nav"
            :index="item.path"
            :key="index"
          >
            <i :class="item.icon"></i>
            <span slot="title">{{item.tilte}}</span>
          </el-menu-item>
        </el-menu>
      </div>
      <div class="rightContent">
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex';
export default {
  name: 'app',
  components: {
  },
  mounted() {
    console.log(this.$route.path)
  },
  data() {
    return {
      lists: []
    }
  },
  computed: mapState([
    'nav'
  ])
}
</script>

<style lang="scss">
* {
  padding: 0;
  margin: 0;
}
html,
body,
#app {
  width: 100vw;
  height: 100vh;
}
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  .layout {
    width: 100vw;
    height: 100vh;
    display: flex;
    .leftMenu {
      flex-basis: 200px;
    }
    .rightContent {
      flex: 1;
      background: wheat;
    }
  }
}
</style>

六、在router里加入vuex的存储逻辑

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import store from '@/store'
import { getNavData } from '@/api/index'
Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'HomePage',
    redirect:'/home',
    component: Home
  }
]

const router = new VueRouter({
  linkActiveClass:'selected',
  routes
})

// 路由拦截,在url地址跳转之前执行
router.beforeEach((to,from,next)=>{
  addRoutes();
  next()
})

function addRoutes(){
  if(store&&store.state.nav.length == 0 ){
    getNavData().then(res=>{
      console.log(res);
      let { code, menuList } = res.data;
      if(code ==200){
        // 拼接路由数据
        store.dispatch('SET_NAV',menuList)
        let data = routesData(menuList);
        // 动态路由 addRoutes
        router.addRoutes(data);
      }
    })
  }
}

function routesData(menuList){
  menuList.forEach(item=>{
    routes.push({
      path:item.path,
      name:item.name,
      meta:{title:item.title},
      component:()=>import(`../views/content/${item.component}`)
    })
  })
  return routes;
}

export default router

Logo

前往低代码交流专区

更多推荐