vue如何点击多个tab标签打开关闭多个页面

点击多个tab标签打开关闭多个页面

需求

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

效果图

vue如何点击多个tab标签打开关闭多个页面_第1张图片

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中

4.在TagsView中

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中的路由,让最后一个路由作为激活项

vue tab页多页面切换

实现路由发生变化时,新增一个tab标签页,点击其他标签时切换到对应的页面,刷新网页同时保留状态

在这里插入图片描述

这里就直接说它实现的代码就OK!!!

VueX记录下每次新增后的tab标签页路由

store.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {
    // 路由导航start
    // 缓存组件页面
    catch_components: [],
    // 当前选中的菜单 - 默认选择首页
    activePath: '/index',
    // 菜单项 - 默认需要展示的页面()
    tabList: [{
      path: '/index',
      label: '首页',
      name: 'index',
      fullPath: "/index"
    }],
    // 路由导航end
  },
  // 更改vuex的store中状态的唯一方法 - 同步操作
  mutations: {
    // 路由导航start
    //清空vuex数据
    clearVUEX(state) {
      state.catch_components = []
      state.activePath = 'index'
      state.tabList = [{
        path: '/idnex',
        label: '首页',
        name: 'index',
        fullPath: "/index"
      }]
    },
    // 跳转页面执行
    selectMenu(state, submenu) {
      // 首页就是 wellcome   也就是 home
      if (submenu.name === 'index') {
        submenu.name = 'index'
        label.path = '首页'
        submenu.path = '/index'
        submenu.fullPath= '/index'
      }
      // 当前选中菜单
      var activePath = submenu.name
      // 历史已选中菜单列表
      var oldTabList = state.tabList
      // 将菜单信息添加到tablist - 添加时判断是否已有该路由标签
      var result = oldTabList.some(item => {
        if (item.name === activePath) {
          // console.log('--------', item.fullPath != submenu.fullPath)
          // 有该路由标签是否为多次点击(相当于查看同路由下的详情,该过程只改变了参数)
          if (!item.fullPath != submenu.fullPath) {
            item.fullPath = submenu.fullPath
          }
          return true
        }
      })
      // 如果不包含该对象,则添加
      if (!result) {
        oldTabList.push({
          path: submenu.name,
          name: submenu.name,
          label: submenu.label,
          fullPath: submenu.fullPath
        })
      }
      // 重新赋值标签路由和当前选中菜单
      state.activePath = activePath
      state.tabList = oldTabList
    },
    // 添加keepalive缓存
    addKeepAliveCache(state, val) {
      // 如果是首页不缓存
      if (val === 'index') {
        return
      }
      // console.log(state.catch_components)
      // 添加时判断,如果该组件已存在,便不添加
      if (state.catch_components.indexOf(val) === -1) {
        // 不存在,缓存页面
        state.catch_components.push(val)
      }
    },
    // 删除keepalive缓存
    removeKeepAliveCache(state, val) {
      let cache = state.catch_components
      for (let i = 0; i < cache.length; i++) {
        if (cache[i] === val) {
          cache.splice(i, 1);
        }
      }
      state.catch_components = cache
    },
    //关闭菜单
    closeTab(state, val) {
      // 重新赋值
      state.activePath = val.activePath
      state.tabList = val.tabList
    },
    // 点击标签选择菜单
    changeMenu(state, val) {
      state.activePath = val
    },
    // 路由导航end
  },
  actions: {
  }
})

根据自己的需求定义一个展示路由标签组件vue文件

BScroll :当路由标签过多时,用于横向滚动标签页

 



若F5或者强刷新页面时需要保留当前tab路由数据,在App.vue中插入代码

    created() {
      //在页面刷新时将vuex里的信息保存到sessionStorage里
      window.addEventListener("beforeunload", () => {
        sessionStorage.setItem("store", JSON.stringify(this.$store.state))
      })
    
    },

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

你可能感兴趣的:(vue如何点击多个tab标签打开关闭多个页面)