最近我在写一个“项目”?遇到了以前没有接触到的一个知识点——“面包屑”。
写下来,我所理解的思路,一是为了看能不能帮助到大家,二是自己肯定不是已经完全理解、印在脑子里了,所以方便自己随时复习~
我们先来看一下功能:
当我们点击【aside 】区的【menu】时,我们的【header】上会添加相应的【span】,且会跳转相应的路由;细心的同学可以发现,在我们的展示区上方会出现我们点击时相同名字的【tag】标签,它们也对应相应的路由跳转;并且呢,我们的【tag】标签可以删除,我们的“面包屑”也会进行相应的删除。这就是我们的“面包屑”与【Tag】相应的功能。
而对于这个系统的代码层面,我们应该怎么实现“面包屑”与【Tag】以及相互联动的功能呢?
首先我们应该要知道,我们的“面包屑”它所在的区域是我们的【Header】部分,而【Tag】属于内容区,但是它又不属性每一个页面,而是属性公共部分。所以“面包屑”与【Tag】处在不同的两个组件中,这就牵扯到了不同组件间的通信,在这里,我们用到了vuex对我们不同组件间的数据的交互。
Header.vue:
<!-- 面包屑 -->
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="item in tags" :key="item.path" :to="{ path: item.path }">{{item.label}}</el-breadcrumb-item>
</el-breadcrumb>
computed:{
// ...mapState({
// tags:state=>state.tab.tabList
// })
tags(){
return this.$store.state.tab.tabList
}
}
state:{
isCollapse: false,//控制菜单是否展开
tabList:[
{
path:'/',
name:'home',
label:'首页',
icon:'s-home',
url:'Home/Home'
}
// 面包屑的数据
]
},
起初,我们给state中定义一个初始数据(首页的数据),for循环state中的tabList这个数组的每一项,并且动态渲染其中的label和跳转路径。
Asider.vue:
<h4>{{isCollapse?'后台':'通用后台管理系统'}}</h4>
<el-menu-item @click='toMenu(item)' v-for="item in nochild" :key="item.path" :index="item.path">
<i :class="`el-icon-`+item.icon"></i>
<span slot="title">{{item.label}}</span>
</el-menu-item>
<el-submenu v-for="item in haschild" :key="item.label" :index="item.label">
<template slot="title">
<i :class="`el-icon-`+item.icon"></i>
<span slot="title">{{item.label}}</span>
</template>
<el-menu-item-group v-for="(subItem) in item.children" :key="subItem.path" :index='subItem.path'>
<el-menu-item @click="toMenu(subItem)">{{subItem.label}}</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
toMenu(item){
this.$router.push(item.path)
this.$store.commit('SELECTMENU',item)
},
},
computed:{
nochild(){
return this.menu.filter(item =>!item.children)
},
haschild(){
return this.menu.filter(item =>item.children)
},
isCollapse(){
return this.$store.state.tab.isCollapse
}
}
SELECTMENU(state,val){
// 判断添加的数据是否为首页
if(val.name !== 'home'){
const index = state.tabList.findIndex(item=>item.name === val.name)
// 当Index为-1时,表示tabList中没有,则可以添加面包屑
if(index === -1){
state.tabList.push(val)
}
}
},
我们的Menu分为有子级菜单和没有子级菜单的,“面包屑”和我们的一级菜单有关,所以我们可以给菜单绑定一个事件,当我们点击这个菜单时,我们把这个点击的路由信息添加到state的tabList中(使用state中的mutation方法添加),通过渲染,就形成了,点击一个一级菜单,我们的“面包屑”就添加一个。
Tags.vue:
<template>
<div class="tags">
<el-tag
v-for="(item,index) in tags"
:key="item.path"
:closable="item.name !== 'home'"
:effect="$route.name === item.name ? 'dark':'plain'"
@click = 'clickTags(item)'
@close = 'handleTag(item,index)'
size="small"
>
{{ item.label }}
</el-tag>
</div>
</template>
computed:{
...mapState({
tags:state=>state.tab.tabList
})
},
methods:{
// 调用store中的mutation
...mapMutations(['closeTag']),
// 点击TAG跳转路由
clickTags(item){
this.$router.push(item.path)
},
// 点击删除按钮,删除TAG
handleTag(item,index){
// 调用mutation中的CLOSETAG事件
this.closeTag(item)
// 删除后的tags的长度
const length = this.tags.length
// 如果当前点击的tag的name 与当前路由的name不一致,不作反应
if(item.name !== this.$route.name){return}
// 点击删除的tag是最后一个
if(index === length){
this.$router.push({
name:this.tags[index-1].name
})
}else{
this.$router.push({
name:this.tags[index].name
})
}
}
}
// 删除指定tag标签
closeTag(state,val){
const index = state.tabList.findIndex(item => val.name === item.name)
state.tabList.splice(index,1)
}
首先,是点击【Tag】标签时,我们的路由跳转,这个很简单,我们可以给【Tag】标签绑定一个点击事件,当我们点击时,通过编程式路由,进行路由的跳转;第二步是,当我们点击标签上的关闭按钮时,我们的标签删除,和相应的路由跳转,在这其中,我们有一定的逻辑,详细代码写在上面了,有需要的同学可以看一下。删除标签用到了【Tag】上的close事件,点击调用handleTag事件,事件里调用mutation中的closeTag方法,遍历找到在tabList中与点击的路由相同name的项,用数组中splice方法删除,state中的数据被删除了,页面渲染的【Tag】自己也删除了。
我自己过了几遍,我自己大概能理解,如果有同学发现,哪里写错了,可以评论区指出来,大家一起学习,一起进步!!!
今天就到这了,希望对大家有帮助。拜比~