[vue]利用router动态渲染菜单项和子菜单项
程序员文章站
2022-07-14 18:25:36
...
目录
非动态渲染的代码:
Home.vue组件
<template>
<div>
<el-container>
<el-aside width="200px">
<el-menu @select="menuClick">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>导航一</span>
</template>
<el-menu-item index="/home/test1">选项1</el-menu-item>
<el-menu-item index="/home/test2">选项2</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<router-view/>
</el-main>
</el-container>
</div>
</template>
<script>
export default {
name: "Home",
methods: {
//菜单**回调
/**
* index:选中菜单项的index,在这里我们用作为跳转路径
* indexPath:选中菜单项的index path
*/
menuClick(index){
//路由跳转
this.$router.push(index)
},
},
},
};
</script>
路由配置router.js
非完整代码,忽略了import 和Vue.use(VueRouter)
const routes = [{
path: '/'
,name: 'Login'
,component: Login
},
{
path: '/home'
,name: '导航一'
,component: Home
,children: [{
path: '/test1'
,name: Test1'
,component: Test1
},
{
path: '/test2'
,name: 'Test2'
,component: Test2
}
]
},
]
这种方式每次新添加一个菜单项都需要我们去在Hone.vue中添加,然后在router.js配置路由.比较麻烦点.下面我们就将利用vue中的$router获取到router.js中的配置项,然后去动态的渲染Home.vue中的菜单项和子菜单项的信息.这样每次我们只需要修改router.js里面的东西就可以了,不用再去修改Home.vue中的内容了
动态渲染菜单项
Home.vue
使用this.$router.options.routes获取到router.js中各项路由配置的信息,其中的每一个item都是一个路由配置项.
hidden:标识位,表示是否渲染该项路由信息
<template>
<div>
<el-container>
<el-header class="homeHeader">
<div class="title">人事管理</div>
<el-dropdown class="userInfo" @command="commandHandler">
<span class="el-dropdown-link">
{{ user.name }}<i><img :src="user.userface" alt="" /></i>
</span>
<el-dropdown-menu slot="dropdown">
<!-- 每个下拉框的item中的command相当于id一样用于标记每个item -->
<el-dropdown-item command="userinfo">个人中心</el-dropdown-item>
<el-dropdown-item command="setting">设置</el-dropdown-item>
<el-dropdown-item command="logout" divided>
退出登录</el-dropdown-item
><!--divided表示分割线 -->
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-container>
<el-aside width="200px">
<el-menu @select="menuClick">
<el-submenu index="1" v-for="(item,index) in this.$router.options.routes" :key="index" v-if="!item.hidden">
<template slot="title">
<i class="el-icon-location"></i>
<span>{{item.name}}</span>
</template>
<el-menu-item :index="child.path" v-for="(child,indexj) in item.children" :key="indexj">{{child.name}}</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "Home",
methods: {
//菜单**回调
/**
* index:选中菜单项的index,在这里我们用作为跳转路径
* indexPath:选中菜单项的index path
*/
menuClick(index){
this.$router.push(index)
},
},
};
</script>
router.js配置
const routes = [{
path: '/'
,name: 'Login'
,component: Login
,hidden:true
},
{
path: '/home'
,name: '导航一'
,component: Home
,hidden:false //此处的hidden只是个标记相当于bool flag,并不会把该路由隐藏
,children: [{
path: '/test1'
,name: '选项一'
,component: Test1
},
{
path: '/test2'
,name: '选项二'
,component: Test2
}
]
},
]
通过数据库进行菜单动态渲染.....待更新
代码优化v-for v-if同时使用性能不太好
上面的是同时使用v-for和v-if,下面这个优化后的代码通过计算属性完成对this.$router.options.routes的过滤,将结果再给v-for使用,
<template>
<div>
<el-container>
<el-header class="homeHeader">
<div class="title">人事管理</div>
<el-dropdown class="userInfo" @command="commandHandler">
<span class="el-dropdown-link">
{{ user.name }}<i><img :src="user.userface" alt="" /></i>
</span>
<el-dropdown-menu slot="dropdown">
<!-- 每个下拉框的item中的command相当于id一样用于标记每个item -->
<el-dropdown-item command="userinfo">个人中心</el-dropdown-item>
<el-dropdown-item command="setting">设置</el-dropdown-item>
<el-dropdown-item command="logout" divided>
退出登录</el-dropdown-item
><!--divided表示分割线 -->
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-container>
<el-aside width="200px">
<el-menu router>
<el-submenu index="1" v-for="(item,index) in menus" :key="index" >
<template slot="title">
<i class="el-icon-location"></i>
<span>{{item.name}}</span>
</template>
<el-menu-item :index="child.path" v-for="(child,indexj) in item.children" :key="indexj">{{child.name}}</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
//存入浏览器的本地session域中
user: JSON.parse(window.sessionStorage.getItem("user")),
};
}, //data-end
computed:{
//在计算属性这里进行了过滤(相当于使用了v-if),然后再将过滤后的值给v-for使用
menus(){
let arr=[''];
arr = this.$router.options.routes.filter(item=>{
return item.hidden==false;
})
console.log(arr);
return arr;
}
},
methods: {
//菜单**回调
/**
* index:选中菜单项的index,在这里我们用作为跳转路径
* indexPath:选中菜单项的index path
* 如果给menu配置一个router属性,就不用写menuClick这个点击事件了:router:会自动将index作为跳转路径进行跳转
*/
// menuClick(index){
// this.$router.push(index)
// },
commandHandler(cmd) {
if (cmd == "logout") {
//confirm确定框
this.$confirm("确认退出登录, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
//确认时触发
//向后端发送/logout
this.getRequest("/logout");
window.sessionStorage.removeItem("user"); //清空sessionStorage中的值
this.$router.replace("/"); //回到登录页面
})
.catch(() => {
//取消时触发
this.$message({
type: "info",
message: "已取消操作",
});
});
}
},
},
};
</script>
<style>
.homeHeader {
background-color: #409eff;
display: flex;
/* 竖直方向上居中 */
align-items: center;
/*在弹性盒对象的 <div> 元素中的各项周围留有空白*/
justify-content: space-between;
padding: 0px 15px;
box-sizing: border-box;
}
/* header中的'人事管理'字体设置 */
.homeHeader .title {
font-size: 30px;
font-family: 华文行楷;
color: #ffffff;
}
/* 在鼠标放在右上角的抽屉式dropdown时,鼠标变为手指 */
.homeHeader .userInfo {
cursor: pointer;
}
.el-dropdown-link img {
width: 48px;
height: 48px;
border-radius: 24px;
margin-left: 8px;
}
.el-dropdown-link {
display: flex;
align-items: center;
}
</style>
上一篇: 关于菜单项中文件选择框的事件处理