需求:现将页面分为Header LeftSideBar Main三大模块 左侧LeftSideBar为menu菜单,点击菜单每一项,在Main中出现上部为tag标签,下部为内容 可打开多个tag标签 ,可内容切换 ,可关闭

效果图

1.router.js中(在LeftSideBar组件中现在有两个菜单项icons和tabs)

{
      path:'/addtab',
      redirect:'/addtab/index',//重定向 输入/addtab 地址会变为/addtab/index
      component: Main,
      children:[
        {
          path:'index',//当addtab/index匹配成功时 TabContent会被渲染在Main中的router-view中
          name:'TabContent',
          component:()=>import("@/components/TabContent")
        }
      ]
},
{
      path:'/addicon',
      redirect:'/addicon/index',
      component: Main,
      children:[
        {
          path:'index',
          name:'IconContent',
          component:()=>import("@/components/IconContent")
        }
      ]
}

请戳动态组件嵌套路由

2.this.$router.push({name:"TabContent",params:{}})  实现点击左侧tab  打开组件main  

3.在main中

<template>
  <div>
    <TagsView/>
    <router-view></router-view>
  </div>
</template>

4.在TagsView中

<template>
  <div class="tags-view-wrapper">
    <router-link class="tags-view-item" :to="item" :key="item.path" :class="isActive(item)?'active':''" v-for="(item) in Array.from(visitedViews)">
      {{item.params.name}}
      <span class='el-icon-close' @click.prevent.stop='closeSelectedTag(item)'></span>
    </router-link>
  </div>
</template>

a.添加标签的方法

visitedViews是存放路由信息的数组


addTags(){
     const route=this.$route;//获取地址栏路由
     this.$store.commit({
     type:'addTags',
     route
 })
}
在store.js中
addTags(state, payload) {
      let flag = state.visitedTags.some(
        item => item.path === payload.route.path
      );//打开标签后,判断数组中是否已经存在该路由
      if (!flag) {
        state.visitedTags.push(
          Object.assign(
            {},
            {
              path: payload.route.path,
              name: payload.route.name,
              params: payload.route.params
            }
          )
        );
      } //数组中路由存在不push ,单击左侧路由变化,点击标签路由变化均触发
    } //添加标签

第一次点击是在mountd中触发addTags方法,后来的每次点击路由均会变化 ,使用watch监听触发

 watch:{
      $route(){
        this.addTags();
      }//地址栏变化了就触发这个添加方法
    }

b.关闭标签

 在store.js中   
 closeTags(state, payload) {
      for (const [key, item] of state.visitedTags.entries()) {
        if (item.path === payload.view.path) {
          state.visitedTags.splice(key, 1);
          break;
        }
      }
    } //如果要关闭的标签在路由中存在则删除     
 在tagviews中
     isActive(route) {
        return route.path === this.$route.path
      },//当前地址栏路径是否与渲染的路径相同 样式匹配
      closeSelectedTag(view){
         this.$store.dispatch({
           type:"closeTags",
           view
         }).then((views)=>{
            此时的views是指的被删除后的visitedViews数组中存在的元素
           if (this.isActive(view)) {
            当前关闭的标签是否是被选中的标签
             const latestView = views.slice(-1)[0];
             if (latestView) {
               this.$router.push(latestView);//如果数组不为空则让选中的标签为紧邻关闭标签的那一个
             } else {
               this.$router.push('/') ;//如果为空则页面跳转到/
             }
           }
         })
      }

说一下思路:点击左侧的每一项都会打开一个组件(对应一个路由)  第一次点击时将路由信息push到visitedViews中 后来的每次点击都是通过watch $route执行添加标签方法 

删除时要考虑是否是对激活项进行关闭 若是则先删除数组中要关闭的标签的那个路由,然后获取剩余visitedViews中的路由,让最后一个路由作为激活项

Logo

前往低代码交流专区

更多推荐