前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue2动态路由

Vue2动态路由

作者头像
用户5899361
发布2023-03-25 12:47:53
8990
发布2023-03-25 12:47:53
举报
文章被收录于专栏:学习java的小白学习java的小白

应用场景:

    一般管理端的菜单栏是根据登录用户角色不同,动态生成的,在vue中我们不止菜单栏需要动态生成,同时我们路由也需要动态生成。

使用到的组件:

组件名称

组件版本

组件作用

axios

1.3.4

用于发送请求获取数据

element-ui

2.15.13

前端ui组件库,制作页面使用

vue-router

3.5.1

vue路由组件

vuex

3.6.2

路由状态管理

mockjs

1.1.0

模拟后台返回数据接口

代码实现:

    项目结构:

    axios相关代码

    http.js

代码语言:javascript
复制
import axios from 'axios'
import router from '@/router/index.js'
import ElementUI from 'element-ui'
const request = axios.create({
  // baseURL: 'http://192.168.1.150:8888/'
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  }
})

request.interceptors.response.use(config => {
  const code = config.data.code
  if (code === 200) {
    return config
  } else {
    ElementUI.Message('服务忙')
    return Promise.reject
  }
}, error => {
  switch (error.response.status) {
    case 404:
      router.push('/404')
      break
    case 500:
      ElementUI.Message('error')
  }
  return Promise.reject
})
export default request

     login.js

代码语言:javascript
复制
import request from '@/utils/http.js'

/**
 * 获取验证码
 */
export function code () {
  return request({
    url: '/getCode',
    method: 'get'
  })
}
/**
 * 登录
 */
export function loginAPI (loginInfo) {
  return request({
    url: '/login',
    method: 'post',
    data: {
      loginInfo
    }
  })
}

/**
 * 获取菜单
 */
export function getMenu () {
  return request({
    url: '/sys/getMenu',
    method: 'post'
  })
}

mock.js

代码语言:javascript
复制
import Mock from 'mockjs'

const Random = Mock.Random
const R = {
  code: 200,
  message: '执行成功',
  data: null
}
// 获取验证码
Mock.mock('/getCode', 'get', () => {
  R.data = {
    token: Random.string(32),
    imageUri: Random.dataImage('100x100', '8878')
  }
  return R
})
// 登录
Mock.mock('/login', 'post', (value) => {
  console.log(value)
  R.data = {
    token: 'token'
  }
  return R
})
// 获取菜单栏信息
Mock.mock('/sys/getMenu', 'post', () => {
  const menu = [{
    id: 1,
    title: '系统设置',
    name: 'settings',
    path: '/sys',
    icon: 'el-icon-setting',
    component: '/sys/SysSettings.vue',
    children: [
      {
        id: 2,
        title: '用户管理',
        name: 'user',
        path: '/sys/user',
        component: '/sys/UserInfo.vue',
        icon: 'el-icon-user'
      },
      {
        id: 3,
        title: '角色管理',
        name: 'role',
        path: '/sys/role',
        component: '/sys/RoleInfo.vue',
        icon: 'el-icon-menu'
      },
      {
        id: 4,
        title: '权限管理',
        name: 'menu',
        path: '/sys/menu',
        component: '/sys/MenuInfo.vue',
        icon: 'el-icon-menu'
      }
    ]
  }]
  const role = []
  R.data = { menu, role }
  return R
})

vuex相关代码

menu.js

代码语言:javascript
复制
import Vue from 'vue'
import Vuex from 'vuex'
import { getMenu } from '@/api/login.js'

Vue.use(Vuex)

export default {
  state: {
    menuList: [],
    flag: false
  },
  getters: {
  },
  mutations: {
    updateMenu (state, value) {
      state.menuList = value
    },
    updateFlag (state, value) {
      state.flag = value
    }
  },
  actions: {
    async httpGetMenu (store) {
      const { data } = await getMenu()
      store.commit('updateMenu', data.data.menu)
      store.commit('updateFlag', true)
    }
  }
}

index.js 

代码语言:javascript
复制
import Vue from 'vue'
import Vuex from 'vuex'
import menu from '@/store/modules/Menu.js'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    token: ''
  },
  getters: {
  },
  mutations: {
    updateToken (state, value) {
      state.token = value
      localStorage.setItem('token', value)
    },
    restState (stste) {
      stste.token = ''
    }
  },
  actions: {
  },
  modules: {
    namespaced: true,
    menu
  }
})

vue-router

代码语言:javascript
复制
import Vue from 'vue'
import VueRouter from 'vue-router'
import UserLogin from '@/views/UserLogin.vue'
import HomeIndex from '@/views/HomeIndex.vue'
import store from '@/store/index.js'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    name: 'login',
    component: UserLogin
  },
  {
    path: '/home',
    name: 'home',
    component: HomeIndex,
    children: []
  }

]

const router = new VueRouter({
  routes
})
router.beforeEach(async (to, form, next) => {
  const flag = store.state.menu.flag
  if (!flag) {
    await store.dispatch('httpGetMenu')
    const menuList = store.state.menu.menuList
    for (const i in menuList) {
      if (menuList[i].children) {
        for (let j = 0; j < menuList[i].children.length; j++) {
          const childrenMenu = {
            path: menuList[i].children[j].path,
            name: menuList[i].children[j].name,
            children: []
          }
          childrenMenu.component = () => import('@/views' + menuList[i].children[j].component)
          router.addRoute('home', childrenMenu)
          next({ ...to, replace: true })
        }
      }
    }
  }
  next()
})

// 获取原型对象push函数
const originalPush = VueRouter.prototype.push

// 获取原型对象replace函数
const originalReplace = VueRouter.prototype.replace

// 修改原型对象中的push函数
VueRouter.prototype.push = function push (location) {
  return originalPush.call(this, location).catch(err => err)
}

// 修改原型对象中的replace函数
VueRouter.prototype.replace = function replace (location) {
  return originalReplace.call(this, location).catch(err => err)
}
export default router

home.vue

代码语言:javascript
复制
<template>
  <div class="home_root">
    <el-container>
      <el-header
        >物业管理
        <el-dropdown :hide-on-click="false">
          <span class="el-dropdown-link">
            设置<i class="el-icon-arrow-down el-icon--right"></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item>个人中心</el-dropdown-item>
            <el-dropdown-item @click.native="loginOut()">退出</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </el-header>
      <el-container>
        <el-aside width="200px">
          <el-col>
            <el-menu
              default-active="2"
              class="el-menu-vertical-demo"
              background-color="#545c64"
              text-color="#fff"
              active-text-color="#ffd04b"
            >
              <el-submenu
                :index="menu.id + ''"
                v-for="menu in menuList"
                :key="menu.id"
              >
                <template slot="title">
                  <i :class="menu.icon"></i>
                  <span>{{ menu.title }}</span>
                </template>
                <el-menu-item
                  :index="children.id + ''"
                  v-for="children in menu.children"
                  :key="children.id"
                >
                  <template slot="title">
                    <div @click="openUri(children.path)">
                      <i :class="children.icon"></i>
                      <span slot="title">{{ children.title }}</span>
                    </div>
                  </template>
                </el-menu-item>
              </el-submenu>
            </el-menu>
          </el-col>
        </el-aside>
        <el-main>
          <router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
export default {
  computed: {
    menuList () {
      return this.$store.state.menu.menuList
    }
  },
  methods: {
    handleClose (tag) {
      this.tags.splice(this.tags.indexOf(tag), 1)
    },
    openUri (uri) {
      this.$router.push(uri)
    },
    loginOut () {
      console.log('loginOut')
      localStorage.clear()
      sessionStorage.clear()
      this.$store.commit('restState')
      this.$router.push('/')
    }
  }
}
</script>

<style lang="less" scoped>
.home_root {
  padding: 0;
  margin: 0;
  height: 100vh;
}
.el-container {
  padding: 0;
  margin: 0;
  height: 100%;
}
.el-header,
.el-footer {
  background-color: #b3c0d1;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #d3dce6;
  color: #333;
  text-align: center;
  line-height: 200px;
}

.el-main {
  background-color: #e9eef3;
  color: #333;
  // text-align: center;
  // line-height: 160px;
  padding: 0;
}

body > .el-container {
  margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
  line-height: 260px;
}

.el-container:nth-child(7) .el-aside {
  line-height: 320px;
}
.el-dropdown {
  float: right;
}
.el-dropdown-link {
  cursor: pointer;
  color: #060606;
}
.el-icon-arrow-down {
  font-size: 12px;
}
.el-col-24 {
  height: 100%;
  .el-menu {
    height: 100%;
  }
}
</style>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档