Vue 面包屑

最近我在写一个“项目”?遇到了以前没有接触到的一个知识点——“面包屑”。

写下来,我所理解的思路,一是为了看能不能帮助到大家,二是自己肯定不是已经完全理解、印在脑子里了,所以方便自己随时复习~

我们先来看一下功能:

当我们点击【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】自己也删除了。

猜你喜欢

转载自blog.csdn.net/m0_60237095/article/details/127504437