Vue开发实例(九)动态路由实现左侧菜单导航

之前在【Vue开发实例(六)实现左侧菜单导航】文中实现了菜单的导航,本篇是在那个基础上改造的。

动态路由实现左侧菜单导航

  • 一、动态菜单创建
  • 二、根据菜单数据来创建路由
  • 三、添加路由已加载标记,省的每次点击菜单都要加载

一、动态菜单创建

假如我定义了3条路由,分别是 ‘/index/menu1’,‘/index/menu2’,‘/index/menu3’
但当前登录的用户只有 ‘/index/menu1’,‘/index/menu2’ 两条路由的权限,如果按照【Vue开发实例(六)实现左侧菜单导航】的做法,可以直接在浏览器输入’/index/menu3’ 这条路由地址来访问,这显然是不对的,于是我们就需要动态路由。

在前文中,router/index.js下方的3条子路由,假设后端只返回menu1和menu2这2条,也就是这路由,我们只需动态创建2条即可。
在这里插入图片描述

  1. 原来的 menu_data 使用mockjs来返回,模拟后台查询菜单数据返回
    • 在mockjs中定义对象的 /post/menuList 路径get请求
    • 返回参数中除了原来的 name、icon、path 增加了component,用于定义跳转路径。

mock/index.js代码

Mock.mock('/post/menuList', 'get', function () {const menu_data = [{name: '一级菜单1',icon: 'el-icon-location',path: '/index/menu1',component: 'Main1'},{name: '一级菜单2',icon: 'el-icon-document',path: '/index/menu2',component: 'Main2'}]return {menu_data}
});
  1. 修改store/index.js,全部参考代码如下
    在这里插入图片描述
import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './module/moduleA.js';
import moduleB from './module/moduleB.js';Vue.use(Vuex)const state = {username: '牛牛',userState: 0,menu_data: []
}
const mutations = {setUser(state, name) {state.username = name},setUserState(state, data) {state.userState += data},setMenuData(state, data) {state.menu_data = data},
}
const getters = {getUserState(state) {let data;if (state.userState == 0) {data = '无效'} else {data = state.userState + '级'}return data;}
}
const modules = {a: moduleA,b: moduleB
}export default new Vuex.Store({state,mutations,getters,modules
})
  1. router/index.js 里面使用方法 beforeEach 来获取数据,并提交到store

注意:

  • 不要忘记引入axios和store的内容
import axios from "axios";
import store from "@/store/index.js";

在这里插入图片描述

import VueRouter from "vue-router"
import Index from "@/components/Index";
import axios from "axios";
import store from "@/store/index.js";const routes = [//一级路由{path: '/index',name: 'index',component: Index,redirect: 'index/Main',//路由嵌套children:[{path: '/index/Main',component: () => import('@/components/Main/index.vue')},{path: '/index/menu1',component: () => import('@/components/Main/Main1.vue')},{path: '/index/menu2',component: () => import('@/components/Main/Main2.vue')},{path: '/index/menu3',component: () => import('@/components/Main/Main3.vue')}]}
]
const router = new VueRouter({mode:'history',routes
})
router.beforeEach((to, from, next)=>{next();axios.get('/post/menuList').then(res=>{store.commit('setMenuData',res.data.menu_data)});
})
export  default router;
  1. Aside.vue 代码中,data里面的属性menu_data不能直接返回了,需通过computed来返回,并且返回的值是从store里面获取的

Aside.vue 参考代码如下

<template><div style="height: 100%"><el-menubackground-color="#545c64"text-color="#ffffff"active-text-color="#ffd04b"class="el-menu-vertical-demo"router><el-menu-item:index="item.path"v-for="item in menu_data":key="item.name"><i :class="item.icon"></i>{{ item.name }}</el-menu-item></el-menu></div>
</template><script>
export default {name: "Aside",data() {return {};},computed: {menu_data: {get() {return this.$store.state.menu_data;},},},
};
</script><style scoped>
.el-icon-location,
.el-icon-document,
.el-icon-setting {display: inline-flex;align-items: center;justify-content: center;
}
</style>

页面效果
在这里插入图片描述

此时菜单确实只有2个菜单,点击菜单也能对应访问到路由menu1和menu2,但是当我们在地址栏输入 menu3的时候,也能访问,这显然是不对的,因为我们的路由是静态写死的,这里肯定是不合理的,所以需要动态来修改一下。

在这里插入图片描述

二、根据菜单数据来创建路由

目前的路由写法

const routes = [//一级路由{path: '/index',name: 'index',component: Index,redirect: 'index/Main',//路由嵌套children:[{path: '/index/Main',component: () => import('@/components/Main/index.vue')},{path: '/index/menu1',component: () => import('@/components/Main/Main1.vue')},{path: '/index/menu2',component: () => import('@/components/Main/Main2.vue')},{path: '/index/menu3',component: () => import('@/components/Main/Main3.vue')}]}
]

针对上面的情况,我们可以考虑,通过菜单取到的数据,动态添加这个路由,而不是直接写死。

说干就干!!!

  1. 先将router/index.js这3条路由代码删除
const routes = [//一级路由{path: '/index',name: 'index',component: Index,redirect: 'index/Main',//路由嵌套children:[{path: '/index/Main',component: () => import('@/components/Main/index.vue')},]}
]
  1. router/index.js 中创建添加动态路由的方法 buildRouter
let oRouters = router.options.routes;
const buildRouter = () => {let data = store.state.menu_data;data.forEach(item => {let new_router = {path: item.path,component: () => import('../components/Main/' + item.component + '.vue')}oRouters[0].children.push(new_router);})router.addRoutes(oRouters)
}
  1. 在创建动态菜单的同时调用这个函数,修改 router/index.js
router.beforeEach((to, from, next)=>{next();axios.get('/post/menuList').then(res=>{store.commit('setMenuData',res.data.menu_data);//动态创建路由buildRouter();});
})

页面展示,点击访问 index/menu1index/menu2正常
在这里插入图片描述

访问 index/menu3 就不会出现页面内容
在这里插入图片描述
全部参考代码

router/index.js

import VueRouter from "vue-router"
import Index from "@/components/Index";
import axios from "axios";
import store from "@/store/index.js";const routes = [//一级路由{path: '/index',name: 'index',component: Index,redirect: 'index/Main',//路由嵌套children: [{ path: '/index/Main', component: () => import('@/components/Main/index.vue') },]}
]const router = new VueRouter({mode: 'history',routes
})let oRouters = router.options.routes;
const buildRouter = () => {let data = store.state.menu_data;data.forEach(item => {let new_router = {path: item.path,component: () => import('../components/Main/' + item.component + '.vue')}oRouters[0].children.push(new_router);})router.addRoutes(oRouters)
}router.beforeEach((to, from, next) => {next();axios.get('/post/menuList').then(res => {store.commit('setMenuData', res.data.menu_data);//动态创建路由buildRouter();});
})export default router;

三、添加路由已加载标记,省的每次点击菜单都要加载

  1. 修改 store/index.js,在store.js的state添加 属性isLoadRoute: false
    在这里插入图片描述
  2. router/index.js 添加路由的 router.beforeEach 稍作修改
    在这里插入图片描述

store和router的相关代码如下

store/index.js代码

import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './module/moduleA.js';
import moduleB from './module/moduleB.js';Vue.use(Vuex)const state = {username: '牛牛',userState: 0,menu_data: [],isLoadRoute: false,
}
const mutations = {setLoadRoute(state, data) {state.isLoadRoute = data},setUser(state, name) {state.username = name},setUserState(state, data) {state.userState += data},setMenuData(state, data) {state.menu_data = data},}
const getters = {getUserState(state) {let data;if (state.userState == 0) {data = '无效'} else {data = state.userState + '级'}return data;}
}
const modules = {a: moduleA,b: moduleB
}export default new Vuex.Store({state,mutations,getters,modules
})

router/index.js代码

import VueRouter from "vue-router"
import Index from "@/components/Index";
import axios from "axios";
import store from "@/store/index.js";const routes = [//一级路由{path: '/index',name: 'index',component: Index,redirect: 'index/Main',//路由嵌套children: [{ path: '/index/Main', component: () => import('@/components/Main/index.vue') },]}
]const router = new VueRouter({mode: 'history',routes
})let oRouters = router.options.routes;
const buildRouter = () => {let data = store.state.menu_data;data.forEach(item => {let new_router = {path: item.path,component: () => import('../components/Main/' + item.component + '.vue')}oRouters[0].children.push(new_router);})router.addRoutes(oRouters)
}router.beforeEach((to, from, next) => {//判断路由是否已经加载过let isLoadRoute = store.state.isLoadRoute;if (!isLoadRoute) {axios.get('/post/menuList').then(res => {store.commit('setMenuData', res.data.menu_data);//动态创建路由buildRouter();//设置已经加载过的标记store.commit("setLoadRoute", true);});}next();
})export default router;

此时点击菜单就不会重复加载了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/509731.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis常用指令,jedis与持久化

1.redis常用指令 第一个是key的常用指令&#xff0c;第二个是数据库的常用指令 前面的那些指令都是针对某一个数据类型操作的&#xff0c;现在的都是对所有的操作的 1.key常用指令 key应该设计哪些操作 key是一个字符串&#xff0c;通过key获取redis中保存的数据 对于key…

shell文本处理工具-shell三剑客1

shell脚本常用基础命令2 shell脚本常用基础命令 shell脚本常用基础命令2一、grep用法二、sed用法2.1p参数 &#xff08;显示&#xff09;n参数&#xff08;只显示处理过的行&#xff09; 文本处理三剑客&#xff1a;grep sed awk 一、grep用法 grep -E egrep (扩展搜索正文表…

本地快速部署谷歌开放模型Gemma教程(基于WasmEdge)

本地快速部署谷歌开放模型Gemma教程&#xff08;基于WasmEdge&#xff09; 一、介绍 Gemma二、部署 Gemma2.1 部署工具2.1 部署步骤 三、构建超轻量级 AI 代理四、总结 一、介绍 Gemma Gemma是一系列轻量级、最先进的开放式模型&#xff0c;采用与创建Gemini模型相同的研究和技…

安装Docker及DockerCompose

0.安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stable test 和 nightly 三个更新频道…

大模型基础应用框架(ReACT\SFT\RAG)创新及零售业务落地

如何将大语言模型的强大能力融入实际业务、产生业务价值&#xff0c;是现在很多公司关注的焦点。在零售场&#xff0c;大模型应用也面临很多挑战。本文分享了京东零售技数中心推出融合Agent、SFT与RAG的大模型基础应用框架&#xff0c;帮助业务完成大模型微调、部署和应用&…

【uni-app】condition 启动模式配置,生产环境无效,仅开发期间生效

在小程序开发过程中&#xff0c;每次代码修改后&#xff0c;都会启动到首页&#xff0c;有时非常不方便&#xff0c;为了更高效的开发&#xff0c;有时需要模拟直接跳转到指定的页面&#xff0c; 操作方法如下&#xff1a; 在pages.joson里面配置下列代码&#xff1a; "…

台式电脑电源各线的电压和电流输出和输出电流

台式电脑电源是电脑硬件的重要组成部分。 它为计算机的各个部件提供所需的电压和电流。 不同的硬件设备和组件有不同的电压和电流输出。 下面详细介绍台式电脑电源各线的电压&#xff0c;包括3.3V、5V、12V、-12V、-5V和5VSB&#xff0c;以及它们的输出电流和用途。 3.3V&#…

c语言游戏实战(10):坤坤的篮球回避秀

前言&#xff1a; 这款简易版的球球大作战是博主耗时两天半完成的&#xff0c;玩家需要控制坤坤在游戏界面上移动&#xff0c;来躲避游戏界面上方不断掉下来的篮球。本游戏使用C语言和easyx图形库编写&#xff0c;旨在帮助初学者了解游戏开发的基本概念和技巧。 在开始编写代…

数字经济的下一步:Web3的潜力与前景

引言&#xff1a; 随着区块链技术的迅速发展&#xff0c;数字经济正迎来新的变革时代。在这个数字化时代&#xff0c;Web3作为区块链技术的延伸和演进&#xff0c;正在成为全球数字经济发展的重要方向。本文将深入探讨Web3的潜力与前景&#xff0c;以及它对数字经济发展的深远…

二,几何相交----2,区间相交检测IID--(1)算法

对于空间的线段是否相交&#xff0c;假设都是与x平行&#xff0c;则需要三步 1&#xff0c;对各线段左右端点设置为L,R标志 2&#xff0c;从小到大进行排序 3&#xff0c;线性扫描&#xff0c;从小到大&#xff0c;根据模式判断是否相交&#xff0c;假设不相交&#xff0c;则应…

企业需要知道的数据安全管理产品-堡垒机

随着互联网的发达&#xff0c;数据泄露事件时有发生&#xff0c;保障数据安全至关重要&#xff0c;因此数据安全管理产品也越来越多。今天我们就来聊聊企业都应该知道的数据安全管理产品堡垒机。 第一、什么是堡垒机&#xff1f; 在一个特定的网络环境下&#xff0c;为了保障…

抖店入驻费用是多少?新手入驻都有哪些要求?2024费用明细!

我是电商珠珠 我做电商做了将近五年&#xff0c;做抖店做了三年多&#xff0c;期间还带着学员一起做店。 今天&#xff0c;就来给大家详细的讲一下在抖音开店&#xff0c;需要多少费用&#xff0c;最低需要投入多少。 1、营业执照200元左右 就拿个体店举例&#xff0c;在入…