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

目录
  • 点击多个tab标签打开关闭多个页面
    • 需求
    • 效果图
    • 说一下思路
  • vue tab页多页面切换

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

需求

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

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:当路由标签过多时,用于横向滚动标签页

 <!-- crumbs.vue -->
<template>
  <div class="tags">
    <div class="horizontal-container">
      <div class="scroll-wrapper" ref="scroll">
        <div class="scroll-content">
          <el-tag size="medium" v-for="(tab, index) in tabList" :key="tab.path" @close="handleClose(tab, index)"
            @click="changeMenu(tab)" :closable="tab.name !== 'index'"
            :effect="activePath === tab.name ? 'dark' : 'plain'">
            {{tab.label}}
          </el-tag>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import {
    mapState
  } from 'vuex';
  import BScroll from '@better-scroll/core'
  export default {
    data() {
      return {
        //菜单列表
        menuList: [],
      }
    },
    computed: {
      ...mapState({ // 从 state 中的到的计算属性
        activePath: state => state.activePath, // 已选中菜单
        tabList: state => state.tabList, // tags菜单列表
        catch_components: state => state.catch_components, // keepalive缓存
      })
    },
    mounted() {
      // this.handleCommand()
      this.init()
    },
    methods: {
      init() {
        this.bs = new BScroll(this.$refs.scroll, {
          scrollX: true,
          probeType: 3 // listening scroll event
        })
      },
      // 清空当前vuex数据
      handleCommand() {
        this.$store.commit('clearVUEX')
      },
      // 点击菜单 - 传入name,添加到keepalive缓存页面
      selectMenu(item) {
        // console.log(item.name)
        // 加入keepalive缓存
        this.$store.commit('addKeepAliveCache', item.name)
        //添加tags标签
        //访问wellcome 就代表home
        var name = item.name === 'index' ? 'index' : item.name
        var submenu = {
          path: item.path,
          name: name,
          label: item.meta.title,
          fullPath: item.fullPath
        }
        // console.log(submenu)
        //更新选中菜单
        this.$store.commit('selectMenu', submenu)
        console.log(this.$store.state.tabList)
      },
      // 点击标签跳转路由
      changeMenu(item) {
        // 历史选中菜单
        var oldActivePath = this.$store.state.activePath
        // 首先判断点击的是否是自己,如果是自己则return
        if (oldActivePath === item.name) {
          return
        }
        // 存储菜单
        this.$store.commit('changeMenu', item.name)
        // 页面跳转
        this.$router.push({
          path: item.fullPath
        })
      },
      // 关闭tab标签
      handleClose(tab, index) {
        // 历史选中菜单
        var oldActivePath = this.$store.state.activePath
        // 历史已选中菜单列表
        var oldTabList = this.$store.state.tabList
        // 计算标签个数
        let length = oldTabList.length - 1
        // 删除tabList中的该对象
        for (let i = 0; i < oldTabList.length; i++) {
          let item = oldTabList[i]
          if (item.name === tab.name) {
            oldTabList.splice(i, 1);
          }
        }
        // 删除keepAlive缓存
        this.$store.commit('removeKeepAliveCache', tab.name)
        // 如果关闭的标签不是当前路由的话,就不跳转
        if (tab.name !== oldActivePath) {
          return
        }
        // 如果length为1,必然只剩下首页标签,此时关闭后,更新到首页
        if (length === 1) {
          // 同时存储菜单
          this.$store.commit('closeTab', {
            activePath: 'home',
            tabList: oldTabList
          })
          // tab页向左跳转
          this.$router.push({
            name: oldTabList[index - 1].name
          })
          // 不再向下执行
          return
        }
        // 关闭的标签是最右边的话,往左边跳转一个
        if (index === length) {
          // 同时更新路径
          oldActivePath = oldTabList[index - 1].name
          // 同时存储菜单
          this.$store.commit('closeTab', {
            activePath: oldActivePath,
            tabList: oldTabList
          })
          // tab页向左跳转
          this.$router.push({
            name: oldTabList[index - 1].name
          })
        } else {
          // 同时更新路径
          oldActivePath = oldTabList[index].name
          // 同时存储菜单
          this.$store.commit('closeTab', {
            activePath: oldActivePath,
            tabList: oldTabList
          })
          // tab页向右跳转
          this.$router.push({
            name: oldTabList[index].name
          })
        }
      },
    },
    watch: {
      // 路由发生变化时调用更新tab标签数据
      '$route': {
        handler(newValue) {
          // console.log(newValue, oldValue)
          this.selectMenu(newValue);
        },
        immediate: true
      }
    },
  }
</script>
<style lang="less" scoped="scoped">
  /deep/ .el-tag--medium {
    margin-right: 10px;
  }
  .horizontal-container {
    .scroll-wrapper {
      position: relative;
      width: 100%;
      // margin: 80px auto;
      margin: 0 auto;
      white-space: nowrap;
      // border: 3px solid #42b983;
      border-radius: 5px;
      overflow: hidden;
      .scroll-content {
        display: inline-block;
      }
      .scroll-item {
        height: 40px;
        line-height: 40px;
        // font-size: 24px;
        display: inline-block;
        text-align: center;
        padding: 0 10px;
      }
    }
  }
  /deep/.el-tabs__nav-scroll {
    background: #fff;
  }
  .el-tag {
    cursor: pointer;
    margin-left: 10px;
    border-radius: 2px;
    font-size: 12px;
    color: #1890FF;
    border-color: #1890FF;
  }
  .el-tag--dark {
    color: #fff;
    background-color: #1890FF;
  }
  .el-dropdown-link {
    cursor: pointer;
  }
  .el-icon-arrow-down {
    font-size: 12px;
  }
  .submit-row {
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
    align-items: center;
  }
</style>

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

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

    },

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

(0)

相关推荐

  • 详解vue2.0 使用动态组件实现 Tab 标签页切换效果(vue-cli)

    在 vue 中,实现 Tab 切换主要有三种方式:使用动态组件,使用 vue-router 路由,使用第三方插件. 因为这次完成的功能只是简单切换组件,再则觉得使用路由切换需要改变地址略微麻烦,所以使用的是动态组件实现,如果是在大型应用上,可能使用 vue-router 会方便一些. 先看下最终实现的效果,结构比较简单,顶部的三个 Tab 标签用于切换,内容区域分别为三个子组件. 效果预览 关键代码及分析如下: <template> // 每一个 tab 绑定了一个点击事件,传入的参数对应着

  • vue2.0实现的tab标签切换效果(内容可自定义)示例

    本文实例讲述了vue2.0实现的tab标签切换效果.分享给大家供大家参考,具体如下: 这里利用vue2.0 实现tab标签切换效果 比较实用 初学vue,练习写了一个demo 网上有很多同样的例子,但都只是改text数据,如果我想加入图片或者复杂的dom结构就不实用,今天这个就刚好可以. 先上代码: html部分 [记得引入vue文件哦] <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g

  • VUE的tab页面切换的四种方法

    1.静态实现方法: 效果图: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="widt

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

    目录 点击多个tab标签打开关闭多个页面 需求 效果图 说一下思路 vue tab页多页面切换 点击多个tab标签打开关闭多个页面 需求 现将页面分为Header LeftSideBar Main三大模块 左侧LeftSideBar为menu菜单,点击菜单每一项,在Main中出现上部为tag标签,下部为内容 可打开多个tag标签 ,可内容切换 ,可关闭 效果图 1.router.js中(在LeftSideBar组件中现在有两个菜单项icons和tabs) { path:'/addtab', re

  • Vue实现点击导航栏当前标签后变色功能

    本文实例为大家分享了Vue实现点击导航栏当前标签后变色的具体代码,供大家参考,具体内容如下 效果图 实现 这个功能,借助一个切换标识,当与各标签项 index 对应时切换 css. HTML: <template> <div class="nav"> <!-- 点击切换变色导航栏 --> <ul> <li v-for="(item,index) in nav" :class="{ active: ind

  • vue实现tab标签(标签超出自动滚动)

    当创建的tab标签超出页面可视区域时自动滚动一个tab标签距离,并可手动点击滚动tab标签,实现效果请看GIF图 效果预览GIF图 <template> <div class="main-box"> <button @click="add">添加</button> <div class="main-box-tab"> <i @click="previous"&g

  • vue实现兄弟组件之间跳转指定tab标签页

    目录 兄弟组件之间如何跳转指定tab标签页 场景 vue.js实现tab页面的跳转 tab标签 tab标签对应的展示的内容 vue实例中对应的数据以及函数 兄弟组件之间如何跳转指定tab标签页 场景 index跳转至list的第三个标签栏并刷新列表 // index methods: {      ...      go(){       this.$router.push({         name: 'list',        //要跳转的路由name         query: {

  • js实现点击切换TAB标签实例

    本文实例讲述了js实现点击切换TAB标签.分享给大家供大家参考.具体如下: 这里演示的选项卡效果代码,无jq,纯JS来实现,灰色风格,没有怎么美化,或许看上去比较普通,不过兼容性和操作起来挺舒服的,风格适用于大部分的网站,或许你会用得上. 先来看看运行效果截图: 在线演示地址如下: http://demo.jb51.net/js/2015/js-tab-click-cha-menu-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTM

  • 简单纯js实现点击切换TAB标签实例

    一个不需要jQuery实现的tab选项卡切换效果,代码简洁易用. 默认是鼠标悬停显示tab效果,可将其中的onmouseover 修改为 onclick 点击效果 使用方法: 1.将附件中的index.html中的css样式以及代码部分拷贝到你需要的地方即可 相关链接:几行简单的jQuery代码搞定tab标签切换效果 展示效果图: 效果展示  源码下载 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &

  • vue实现点击当前标签高亮效果【推荐】

    实现点击按钮使当前按钮高亮,其他按钮复原的效果 实现思路 •在data中定义即将渲染的数据,及active data() { return { wpList: [ { name: '食品饮料' }, { name: '鲜花' }, { name: '蛋糕' }, { name: '水果生鲜' }, { name: '服装鞋帽' }, { name: '其它' } ], active:'' } } ... •定义高亮的标签类名 .active { background: #fd7522; bord

  • Vue实现Tab标签路由效果并用Animate.css做转场动画效果的代码第1/3页

    类似于浏览器窗口一样的路由切换逻辑,看着还是挺高大上的,本以为有很多高级的玩意儿,奈何复杂的东西总是由简单的东西拼接而成的,这个功能也不例外. 本篇文章主要描述两个问题: 如何实现这种Tab标签页的路由效果 如何为路由切换添加转场动画. 该功能的开发主要使用到 AntDesignVue 组件库的Tab组件和 Animate.css 效果如下: Tab标签页实现 首先是该组件的模板部分, ContextMenu 组件是我们自定义的右键菜单,后面会说到. a-tabs 组件则是 ant 的组件,具体

  • vuex + keep-alive实现tab标签页面缓存功能

    在开发很多管理系统过程之中,常遇到这种需求,需要对打开路由页面进行缓存,然后在系统页眉提供方便查阅的tab标签进行切换以及对已经缓存页面进行数据刷新和清除数据操作.具体演示如下图所示: 在上面演示中实现了类似 window tab 标签页效果,会对当前数据进行缓存.在浏览器中实现对路由页面的缓存可以减少接口请求,也方便了用户来回切换想搜索的数据列表. 原理 Vue 提供的 keep-alive API实现对路由组件的缓存. include 属性可以绑定一个数组,里面是需要路由组件的 name 值

随机推荐