一、思路、细节

1、利用前面博客所讲的Vuex的知识;定义几个变量

Options:存放tab页对象的容器(主要是路由路径以及tab页的名字)

activeIndex:被激活的tab页路由路径

showName:tab页的标题

Role:用来区分是否是因为左侧菜单被点击造成的路由路径发生改变;

是:pass;不是:nopass

2、左侧导航菜单绑定点击事件

将被点击的菜单名称存放到Vuex中,供路由路径变化监听时,tab页标题显示;

标记一下role为pass,到时新增tab页的时候需要作为判断依据

3、右侧对tab页进行操作

Tab页的点击(切换到被点击的tab页完成路由跳转;标记一下role为nopass,到时新增tab页的时候需要作为判断依据;);

Tab页的移除(删除指定的tab页对象;如果删除的tab页对象处于选中状态,需要将选中状态的下标移到最后一个,因为原来选中的tab页已经删除了;标记一下role为nopass,到时新增tab页的时候需要作为判断依据;))

4、监听路由路径变化

点亮已经存在的tab页(Vuex中showName与option中的哪个tab页对象的name相同,那么就点亮哪一个)

新增tab页(首先路由路径的变化是因为左侧栏的点击,其次要option中不存在的tab页对象)

二、实践、操作

2.1 State.js

export default{resturntName:'哪吒',verificationJwt:null,//这是用来保存用户等登录验证码jwt身份识别的options: [],//存放tab页的容器activeIndex: '',//激活的tab页路由路径showName:'show',//tab页的标题role:""//用来区分是否是因为左侧菜单被点击造成的路由路径发生改变,是:pass;不是:nopass
}

2.2  Mutations.js

export default {// type(事件类型):用于赋值改变state中的数据,可以理解为set方法// payload:官方给它还取了一个高大上的名字:载荷,其实就是一个保存要传递参数的容器setResturantName: (state,payload)=>{state.resturntName = payload.resturntName;},setVerificationJwt: (state, payload) => {state.verificationJwt = payload.verificationJwt;},// 添加tabs(data包含了路由路径跟tab页名字)add_tabs(state, data) {this.state.options.push(data);},// 删除tabs    (route是路由路径)delete_tabs(state, route) {let index = 0;for (let option of state.options) {if (option.route === route) {break;}index++;}this.state.options.splice(index, 1); //删除options里面下标为Index的一个数},// 设置当前激活的tabset_active_index(state, index) {this.state.activeIndex = index;},//设置tab页显示标题set_showName(state, name) {this.state.showName = name;},set_role(state, role) {this.state.role = role;}}

2.3  Getters.js

export default{getResuletName:(state)=>{return state.resturntName;},getShowName:(state) => {return state.showName;},getOptions:(state) => {return state.options;},getRole:(state) =>{return state.role;}
}

2.4  LeftNav.vue

<template><el-menu  router :default-active="$route.path" class="el-menu-vertical-demo" background-color="#334157" text-color="#fff"active-text-color="#ffd04b" :collapse="leftCollapsed"><!-- <el-menu default-active="2" :collapse="collapsed" collapse-transition router :default-active="$route.path" unique-opened class="el-menu-vertical-demo" background-color="#334157" text-color="#fff" active-text-color="#ffd04b"> --><div class="logobox"><img class="logoimg" src="../assets/img/logo.png" alt=""></div><el-submenu :index="'id_'+m.treeNodeId" v-for="m in menus"><template slot="title"><i :class="m.icon"></i>    <span>{{m.treeNodeName}}</span></template><el-menu-item :key="'id_'+m2.treeNodeId" :index="m2.url" v-for="m2 in m.children" @click="showName(m2.treeNodeName)"><i :class="m2.icon"></i><span>{{m2.treeNodeName}}</span></el-menu-item></el-submenu></el-menu>
</template>
<script>export default {name: 'LeftAside',props: ['leftCollapsed'],data: function() {return {menus:[]}},computed: {showLeftAside: function() {return this.leftCollapsed;}},//加载表格数据created(){let url = this.axios.urls.SYSTEM_MENU_TREE;this.axios.post(url,{}).then(resp => {//nsole.log(resp);this.menus=resp.data.result;}).catch(resp => {});},methods: {showName(name) {// 把菜单名称放进去,当成tab页的名称this.$store.commit('set_showName', name)this.$store.commit('set_role', "pass");}}}
</script>
<style>.el-menu-vertical-demo:not(.el-menu--collapse) {width: 240px;min-height: 400px;}.el-menu-vertical-demo:not(.el-menu--collapse) {border: none;text-align: left;}.el-menu-item-group__title {padding: 0px;}.el-menu-bg {background-color: #1f2d3d !important;}.el-menu {border: none;}.logobox {height: 40px;line-height: 40px;color: #9d9d9d;font-size: 20px;text-align: center;padding: 20px 0px;}.logoimg {height: 40px;}
</style>

2.5 Main.vue

<template><el-container class="main-container"><el-aside :class="showLeftAside"><LeftAside :left-collapsed="collapsed"></LeftAside></el-aside><el-container><el-header class="main-header"><TopNav @topnav-collapsed="openCollapsed"></TopNav></el-header><div class="template-tabs"><el-tabs v-model="activeIndex" type="border-card" closable @tab-click="tabClick" @tab-remove="tabRemove"><el-tab-pane :key="item.name" v-for="(item, index) in options" :label="item.name" :name="item.route"></el-tab-pane></el-tabs></div><el-main class="main-center"><router-view></router-view></el-main></el-container></el-container>
</template><script>
//     实现折叠效果
//     点击TopNav折叠LeftAside
//
//     注:
//     1) 父组件Main.Vue
//     2) 子组件TopNav.vue和Leftside.vue
//
//     思路:
//     1)点击TopNav->Mani->LefrtAside
//     2)TopNav->Mani :子组件到父组件 使用时间this.$emit()
//  3)Mani->LefrtAside 父组件到子组件 使用prop// 导入组件import TopNav from '@/components/TopNav.vue'import LeftAside from '@/components/LeftAside.vue'// 导出模块export default {name:'Main',data:function(){return{//asideClass:'main-aside',collapsed:false};},methods:{openCollapsed:function(collapsed){this.collapsed=collapsed;console.log(this.collapsed);},// tab切换时,动态的切换路由tabClick(tab) {// v-model="activeIndex"是路由路径let path = this.activeIndex;this.$router.push({ path: path });this.$store.commit('set_role',"nopass");},tabRemove(targetName) {// console.log(targetName);targetName是路由路径this.$store.commit('set_role',"nopass");// let tabs = this.editableTabs;this.$store.commit('delete_tabs', targetName);// 如果激活tab页被关闭,那么需要激活别的tab页,最后一个tab页被关闭,那么跳转主界面if (this.activeIndex === targetName) {// 设置当前激活的路由if (this.options && this.options.length >= 1) {this.$store.commit('set_active_index', this.options[this.options.length - 1].route);this.$router.push({ path: this.activeIndex });} else {this.$router.push({ path: '/Main' });}}}},watch: {'$route'(to) {// 只要路由发生改变,就会触发此事件(点击左侧菜单时会触发,删除右侧tab页会触发,切换右侧已存在的tab页会触发)let role=this.$store.state.role;let showName=this.$store.getters.getShowNamelet flag = false;//判断是否页面中是否已经存在该路由下的tab页//options记录当前页面中已存在的tab页for (let option of this.options) {//用名称匹配,如果存在即将对应的tab页设置为active显示桌面前端if (option.name === showName) {flag = true;this.$store.commit('set_active_index',  to.path);break;}}//如果不存在,则新增tab页,再将新增的tab页设置为active显示在桌面前端// if(role!='nopass'){}if(role=='pass'){if (!flag) {this.$store.commit('add_tabs', { route: to.path, name: showName});this.$store.commit('set_active_index',  to.path);}}}},components:{TopNav,LeftAside},computed:{showLeftAside:function(){return !this.collapsed?'main-aside':'main-aside-collapsed '},options() {return this.$store.state.options;},//动态设置及获取当前激活的tab页activeIndex: {get() {return this.$store.state.activeIndex;},set(val) {this.$store.commit('set_active_index', val);}}}};
</script>
<style type="text/css">.el-tabs--border-card>.el-tabs__content {padding: 0px;}
</style>
<style scoped>.main-container {height: 100%;width: 100%;box-sizing: border-box;}.main-aside-collapsed {/* 在CSS中,通过对某一样式声明! important ,可以更改默认的CSS样式优先级规则,使该条样式属性声明具有最高优先级 */width: 64px !important;height: 100%;background-color: #334157;margin: 0px;}.main-aside {width: 240px !important;height: 100%;background-color: #334157;margin: 0px;}.main-header,.main-center {padding: 0px;border-left: 2px solid #333;}
</style>

2.6 添加一个子tab页数据

<template><div><el-tabs :tab-position="tabPosition" style="height: 200px;"><el-tab-pane label="游客评论">游客评论管理</el-tab-pane><el-tab-pane label="普通会员评论">普通会员评论管理</el-tab-pane><el-tab-pane label="VIP会员评论">VIP会员评论管理</el-tab-pane><el-tab-pane label="SVIP会员评论">SVIP会员评论管理</el-tab-pane></el-tabs></div>
</template><script>export default {data() {return {tabPosition: '评论管理'};}}
</script><style></style>

2.7 配置一下路由

router/index.js


import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/views/Login'
import Register from '@/views/Register'
import Main from '@/views/Main'
import Articles from '@/views/sys/Articles'//vuex
import VuexPage1 from '@/views/sys/VuexPage1'
import VuexPage2 from '@/views/sys/VuexPage2'
import Comment from '@/views/sys/Comment'
Vue.use(Router)export default new Router({routes: [{path: '/',name: 'Login',component: Login},{path: '/Register',name: 'Register',component: Register},{path: '/Main',name: 'Main',component: Main,children: [{path: '/sys/Articles',name: 'Articles',component: Articles},{path: '/sys/VuexPage2',name: 'VuexPage2',component: VuexPage2},{path: '/sys/VuexPage1',name: 'VuexPage1',component: VuexPage1},{path: '/sys/Comment',name: 'Comment',component: Comment},]}]
})
 

结果:

spa项目开发之tab页实现相关推荐

  1. SPA项目开发之CRUD+表单验证

    目录 一.SPA项目开发之表单验证 二.SPA项目开发之CRUD 一.SPA项目开发之表单验证          我们做项目的都关乎到增删改查的功能,在进行增删改查功能之前,我们必须有一个表单验证. ...

  2. spa项目开发之vue+elementUi实现tab页

    文章目录 实现tab页的具体思路: ①当点击左侧导航菜单时 ②操作上侧的tab页时 实现子tab页 当点击一个菜单栏时,出一个tab 实现tab页的具体思路: ①当点击左侧导航菜单时 获取菜单名,把它 ...

  3. spa项目开发之jwt验证码实现

    实现思路及细节 思路: 登录界面向后台请求验证码,后台就先调用随机函数生成验证码,并且根据验证码生成一张图片,以 base64 字符串的形式传到前台,这时我们还要生成verificationJwt令牌 ...

  4. SPA项目开发之JWT

    1. JWT是什么 JSON Web Token (JWT),它是目前最流行的跨域身份验证解决方案 2. 为什么使用JWT JWT的精髓在于:"去中心化",数据是保存在客户端的. ...

  5. web开发之Tab页的常见实现方法

    tab和内容分离 布局: 用一个大的container div容器包裹住tab-control和tab-content两个div块 给每一个tab-control的项(a标签的href属性)设置锚点 ...

  6. 电影天堂APP项目开发之Python爬虫篇,共18课时/5时33分

    电影天堂APP项目开发之Python爬虫篇,共18课时/5时33分,是电影天堂APP项目开发课程的第一篇章,讲解使用requests和bs4库,爬取和解析电影天堂网站数据,并讲数据保存到SQLite数 ...

  7. vue项目中的tab页实现

    //需要自己弄雪碧图 <template> <div class="tab" id="tab"> <router-link to= ...

  8. 项目开发之git配置

    1.本地安装git配置 安装步骤,这里不详细介绍,软件下载然后安装即可. 查看git安装版本 #git --version 2.git密钥生成 ssh-keygen -t rsa -C "f ...

  9. 页面新开Tab页实现方式

    从毕业到现在接触的东西越来越多,慢慢的发现很多东西都可以进行归纳和整理的.今日,偶尔看项目中的Tab页展现方式,就随手去网上找了下资料,发现这个还是很不错的,方便以后使用,就进行一下记录. 页面基础代 ...

  10. Cypress之处理页面弹框以及多tab页间切换

    上次博客讲解了如何模拟键盘输入和鼠标操作以及拖动页面元素,此次课程将介绍如何处理页面弹框,保证测试案例继续运行.另外,还会介绍如果测试案例跨多个tab页,如何实现多tab页间切换测试.最后介绍cypr ...

最新文章

  1. linux音频驱动dma数据,Linux音频驱动简述
  2. 十一、explain属性介绍
  3. 字符串处理:布鲁特--福斯算法
  4. python一般学多久可以考试_为何Python适合初学者 一般Python要学习多久
  5. 装饰模式在Intermec CK1应用程序中通讯模块的应用
  6. echarts中datazoom相关配置
  7. ES6新特性_Promise封装读取文件---JavaScript_ECMAScript_ES6-ES11新特性工作笔记025
  8. IA64与x64的区别
  9. 10分钟就能搭建远程开发环境?你早点怎么不出现(#`n´)!
  10. Matlab的循环语法
  11. python计算单词长度_附加一个计算单词长度的列表
  12. C# Teechart Pareto图实现 折线显示百分比,多坐标轴显示等
  13. 记一次Maximo移动端app报错的原因
  14. 云端服务器部署前端工程
  15. SQL Server Note [vaynexiao]
  16. 用数组统计学生各个分数段成绩的人数
  17. android高仿今日头条小视频转场切换效果
  18. 2020年6月24日训练总结(codeforces辛路历程)
  19. 风变编程python26_风变编程学习Python的切身体会
  20. 用CentOS 7安装cadence搭建适合IC Design的科研环境(四)——IC617、MMSIM151、calibre2015安装过程step by step

热门文章

  1. windows7初次使用
  2. 我的新书《asp.net开发技巧精讲》
  3. java label 位置_java 怎样设置label的位置
  4. html标签属性大全(囊括CSS、CSS3、H5、XML等)
  5. fedora20 grub2的主题更换
  6. 大数据解决方案,案例分享
  7. 【2021最新版】《全网搜索 6.0》软件使用手册
  8. 排水管网信息系统、市政排水管网信息化智慧化管理
  9. 使用mmdetection做实例分割
  10. 微信h5支付 php sdk_TP5专用微信支付SDK使用简介