spa项目开发之tab页实现
一、思路、细节
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页实现相关推荐
- SPA项目开发之CRUD+表单验证
目录 一.SPA项目开发之表单验证 二.SPA项目开发之CRUD 一.SPA项目开发之表单验证 我们做项目的都关乎到增删改查的功能,在进行增删改查功能之前,我们必须有一个表单验证. ...
- spa项目开发之vue+elementUi实现tab页
文章目录 实现tab页的具体思路: ①当点击左侧导航菜单时 ②操作上侧的tab页时 实现子tab页 当点击一个菜单栏时,出一个tab 实现tab页的具体思路: ①当点击左侧导航菜单时 获取菜单名,把它 ...
- spa项目开发之jwt验证码实现
实现思路及细节 思路: 登录界面向后台请求验证码,后台就先调用随机函数生成验证码,并且根据验证码生成一张图片,以 base64 字符串的形式传到前台,这时我们还要生成verificationJwt令牌 ...
- SPA项目开发之JWT
1. JWT是什么 JSON Web Token (JWT),它是目前最流行的跨域身份验证解决方案 2. 为什么使用JWT JWT的精髓在于:"去中心化",数据是保存在客户端的. ...
- web开发之Tab页的常见实现方法
tab和内容分离 布局: 用一个大的container div容器包裹住tab-control和tab-content两个div块 给每一个tab-control的项(a标签的href属性)设置锚点 ...
- 电影天堂APP项目开发之Python爬虫篇,共18课时/5时33分
电影天堂APP项目开发之Python爬虫篇,共18课时/5时33分,是电影天堂APP项目开发课程的第一篇章,讲解使用requests和bs4库,爬取和解析电影天堂网站数据,并讲数据保存到SQLite数 ...
- vue项目中的tab页实现
//需要自己弄雪碧图 <template> <div class="tab" id="tab"> <router-link to= ...
- 项目开发之git配置
1.本地安装git配置 安装步骤,这里不详细介绍,软件下载然后安装即可. 查看git安装版本 #git --version 2.git密钥生成 ssh-keygen -t rsa -C "f ...
- 页面新开Tab页实现方式
从毕业到现在接触的东西越来越多,慢慢的发现很多东西都可以进行归纳和整理的.今日,偶尔看项目中的Tab页展现方式,就随手去网上找了下资料,发现这个还是很不错的,方便以后使用,就进行一下记录. 页面基础代 ...
- Cypress之处理页面弹框以及多tab页间切换
上次博客讲解了如何模拟键盘输入和鼠标操作以及拖动页面元素,此次课程将介绍如何处理页面弹框,保证测试案例继续运行.另外,还会介绍如果测试案例跨多个tab页,如何实现多tab页间切换测试.最后介绍cypr ...
最新文章
- linux音频驱动dma数据,Linux音频驱动简述
- 十一、explain属性介绍
- 字符串处理:布鲁特--福斯算法
- python一般学多久可以考试_为何Python适合初学者 一般Python要学习多久
- 装饰模式在Intermec CK1应用程序中通讯模块的应用
- echarts中datazoom相关配置
- ES6新特性_Promise封装读取文件---JavaScript_ECMAScript_ES6-ES11新特性工作笔记025
- IA64与x64的区别
- 10分钟就能搭建远程开发环境?你早点怎么不出现(#`n´)!
- Matlab的循环语法
- python计算单词长度_附加一个计算单词长度的列表
- C# Teechart Pareto图实现 折线显示百分比,多坐标轴显示等
- 记一次Maximo移动端app报错的原因
- 云端服务器部署前端工程
- SQL Server Note [vaynexiao]
- 用数组统计学生各个分数段成绩的人数
- android高仿今日头条小视频转场切换效果
- 2020年6月24日训练总结(codeforces辛路历程)
- 风变编程python26_风变编程学习Python的切身体会
- 用CentOS 7安装cadence搭建适合IC Design的科研环境(四)——IC617、MMSIM151、calibre2015安装过程step by step