Vue + Elementui实现多标签页共存的方法


Posted in Javascript onJune 12, 2019

这个主题,早在一年前就已经创建,也写了一些内容,碍于在应用上体验始终不够完美,一直只存着草稿。

经过多个平台实践,多次迭代,一些功能加了又减了,最后还是回归了最精简的版本,已适用于大部分的场景,若有需要,可自行扩展。

关键逻辑

  • 使用 keep-alive 来缓存各标签页
  • 通过 vue-router 的 beforeEach 方法来更新标签信息
  • 通过 vuex 来保存标签信息
  • 通过 vuex 来使关闭页不被缓存

核心代码

定义 vuex 的跨页变量(store/index.js)

import Vuex from 'vuex'
 Vue.use(Vuex)
 export default new Vuex.Store({
  state: {
   worktab: {
    list: [
     {
      name: 'my',
      tabname: '主页',
      path: '/page/my'
     }
    ],
    current: {
     name: 'my',
     tabname: '主页',
     path: '/page/my'
    }
   },
   closingPage: ''
  },
  mutations: {
   worktabRemove (state, p) {
    // 关闭标签
    let ind = state.worktab.list.findIndex(s => s.name === p)
    if (ind > -1) {
     // 清理 keep alive - start
     state.closingPage = state.worktab.list[ind].name
     // 清理 keep alive - end
     state.worktab.list.splice(ind, 1)
    }
    if (p === state.worktab.current.name) {
     // 是当前页,返回上一页
     router.back()
    }
   },
   worktabRoute (state, p) {
    let ind = state.worktab.list.findIndex(s => s.name === p.to.name)
    if (ind > -1) {
     // 标签已存在
     state.worktab.current = state.worktab.list[ind]
    } else {
     // 标签不存在,现在新建
     state.worktab.list.push(p.to)
     state.worktab.current = p.to
    }
    state.closingPage = ''
   }
  },
  actions: {
   worktabRemove ({commit}, p) {
    commit('worktabRemove', p)
   },
   worktabRoute ({commit}, p) {
    commit('worktabRoute', p)
   }
  },
  strict: debug
 })

定义 worktab 标签栏组件,在主容器引用

<template>
  <div class="cp-worktab">
   <el-tabs v-model="activeTab" type="card" @tab-remove="removeTab" @tab-click="clickTab">
    <el-tab-pane
     v-for="t in worktabs"
     :key="t.name"
     :label="t.tabname"
     :name="t.name"
     :closable="t.name !== 'my'"
    >
    </el-tab-pane>
   </el-tabs>
  </div>
 </template>
 <script>
 export default {
  created () {
   // 进来不是主页时等list加载后再更新一次current
   setTimeout(() => {
    this.activeTab = this.$store.state.worktab.current.name
   }, 500)
  },
  watch: {
   '$store.state.worktab.current' (tab) {
    this.activeTab = tab.name
   }
  },
  computed: {
   worktabs () {
    return this.$store.state.worktab.list
   }
  },
  data () {
   return {
    activeTab: 'name'
   }
  },
  methods: {
   clickTab (tab) {
    this.$router.push(this.worktabs[1 * tab.index].path)
   },
   removeTab (name) {
    this.$store.dispatch('worktabRemove', name)
   }
  }
 }
 </script>

路由控制通过beforeEach来更新标签信息

import Vue from 'vue'
 import VueRouter from 'vue-router'
 import store from '@/store'
 import Page from '../components/console/Page.vue'
 import My from '../components/console/My.vue'
 Vue.use(VueRouter)
 // 关联路由与组件
 const routes = [
  {
   name: 'root',
   path: '/'
  },
  {
   path: '/page',
   component: Page,
   children: [
    {
     name: 'my',
     path: 'my',
     component: My,
     meta: {
      tabname: '个人主页'
     }
    }
   ]
  }
 ]
 // 创建路由器
 const router = new VueRouter({
  routes
 })
 router.beforeEach((to, from, next) => {
  next()
  store.dispatch('worktabRoute', {
   to: {
    name: to.name ? to.name : '',
    tabname: (to.meta && to.meta.tabname) ? to.meta.tabname : '',
    path: to.path
   },
   from: {
    name: from.name ? from.name : '',
    tabname: (from.meta && from.meta.tabname) ? from.meta.tabname : '',
    path: from.path
   }
  })
  return
 })
 export default router

主容器通过 closingPage 变量来及时清理关闭页面的缓存

<template>
  <div>
   <cp-worktab></cp-worktab>
   <div class="cp-content">
    <keep-alive :exclude="closingPage">
     <router-view></router-view>
    </keep-alive>
   </div>
  </div>
 </template>
 <script>
 import Worktab from '../module/Worktab'
 export default {
  components: {
   cpWorktab: Worktab
  },
  data () {
   return {}
  },
  computed: {
   closingPage () {
    return this.$store.state.closingPage
   }
  }
 }
 </script>

总结

以上所述是小编给大家介绍的Vue + Elementui实现多标签页共存的方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
JavaScript 给汉字排序实例代码
Jun 28 Javascript
javascript Select标记中options操作方法集合
Oct 22 Javascript
jQuery学习5 jQuery事件模型
Feb 07 Javascript
文本框获得焦点和失去焦点的判断代码
Mar 18 Javascript
js如何设置在iframe框架中指定div不显示
Dec 04 Javascript
JavaScript让网页出现渐隐渐显背景颜色的方法
Apr 21 Javascript
javascript HTML5 Canvas实现圆盘抽奖功能
Apr 11 Javascript
JS弹出窗口的运用与技巧大全
Nov 01 Javascript
js实现带三角符的手风琴效果
Mar 01 Javascript
Three.js实现绘制字体模型示例代码
Sep 26 Javascript
LayUi数据表格自定义赋值方式
Oct 26 Javascript
vue封装数字翻牌器
Apr 20 Vue.js
JavaScript使用面向对象实现的拖拽功能详解
Jun 12 #Javascript
JS实现点击生成UUID的方法完整实例【基于jQuery】
Jun 12 #jQuery
小程序组件之自定义顶部导航实例
Jun 12 #Javascript
vue项目中将element-ui table表格写成组件的实现代码
Jun 12 #Javascript
React 全自动数据表格组件——BodeGrid的实现思路
Jun 12 #Javascript
详解如何提升JSON.stringify()的性能
Jun 12 #Javascript
基于vue-cli搭建多模块且各模块独立打包的项目
Jun 12 #Javascript
You might like
PHP分多步骤填写发布信息的简单方法实例代码
2012/09/23 PHP
js加解密 脚本解密
2008/02/22 Javascript
js中的屏蔽的使用示例
2013/07/30 Javascript
基于jQuery实现文本框缩放以及上下移动功能
2014/11/24 Javascript
JavaScript数据结构与算法之栈详解
2015/03/12 Javascript
浅谈javascript中的闭包
2015/05/13 Javascript
TinyMCE汉化及本地上传图片功能实例详解
2016/05/31 Javascript
js实现上传图片预览方法
2016/10/25 Javascript
ES6(ECMAScript 6)新特性之模板字符串用法分析
2017/04/01 Javascript
ES6使用Set数据结构实现数组的交集、并集、差集功能示例
2017/10/31 Javascript
Vue使用lodop实现打印小结
2019/07/06 Javascript
layui点击弹框页面 表单请求的方法
2019/09/21 Javascript
vscode 使用Prettier插件格式化配置使用代码详解
2020/08/10 Javascript
[55:42]VG vs VGJ.T 2018国际邀请赛淘汰赛BO1 8.21
2018/08/22 DOTA
[01:38:19]夜魇凡尔赛茶话会 第五期
2021/03/11 DOTA
python实现简单flappy bird
2018/12/24 Python
Python中常用的8种字符串操作方法
2019/05/06 Python
pycharm中显示CSS提示的知识点总结
2019/07/29 Python
Python 实现try重新执行
2019/12/21 Python
pytorch实现onehot编码转为普通label标签
2020/01/02 Python
详解Python3 中的字符串格式化语法
2020/01/15 Python
golang/python实现归并排序实例代码
2020/08/30 Python
uniapp+Html5端实现PC端适配
2020/07/15 HTML / CSS
法国票务网站:Ticketmaster法国
2018/07/09 全球购物
澳大利亚二手奢侈品网站:Modsie
2019/09/23 全球购物
马来西亚在线购物:POPLOOK.com
2019/12/09 全球购物
酒店门卫岗位职责
2013/12/29 职场文书
研讨会主持词
2014/04/02 职场文书
电台编导求职信
2014/05/06 职场文书
运动会方阵口号
2014/06/07 职场文书
简单通用的简历自我评价
2014/09/21 职场文书
家长通知书家长意见
2015/06/03 职场文书
导游词之包公祠
2019/11/25 职场文书
深入浅析Redis 集群伸缩原理
2021/05/15 Redis
Nginx缓存设置案例详解
2021/09/15 Servers
MySQL 服务和数据库管理
2021/11/11 MySQL