在后台开发中,常用一种页面标签工具,每次点击菜单栏时,会在页面区域上方增加一个【标签页】如下图,可关闭,可切换页面等功能,常见于后台管理系统中。

以前,我以为这个是利用tabs组件开发的,但是后来看了一些文章才发现,它实际上跟tabs组件没有任何关系(当然你可以用tabs做,实现过程不限于任何技术)

原理:

1 点击菜单栏时,将【菜单项】数据记录在vuex中,或者你存本地的storage中,怎么做都行,但你得保存下来

2 上方标签,通过读取我的路由链,然后用ant vue 【tag】标签渲染(当然你可以用自己方式做)

3 关闭,点击关闭后,要删除路由链,并且要做跳转,当然这里要做判断,如果关闭当前页,则往后面的跳,如果是最后一项,则跳转至开头第一项(路由链中,首页默认设置第一项)

目前,我只简单说到以上的功能,至于其它功能,你可以自己加。

实现:只做实现,质量暂时先不看中

1 vuex中设置路由链,打开你的store/index.js

import Vue from 'vue'
import router from '@/router'
import Vuex from 'vuex'
Vue.use(Vuex)export default new Vuex.Store({state: {tagsRouter: [],},getters: {getTagsRouter(state) {//获取标签路由信息return state.tagsRouter},},mutations: {setRouterTagActive(state, routeItem) {//设置当前的tag页为活动页for (let i = 0; i < state.tagsRouter.length; i++) {let item = state.tagsRouter[i]state.tagsRouter[i].isActive = falseif (state.tagsRouter[i].name === routeItem.name) {state.tagsRouter[i].isActive = true}}console.log(state.tagsRouter)},addRoute(state, routeItem) {//选择菜单后,添加至本地路由信息中let flog = falsefor (let i = 0; i < state.tagsRouter.length; i++) {let item = state.tagsRouter[i]if (state.tagsRouter[i].name === routeItem.name) {flog = truebreak}}if (!flog) {state.tagsRouter.push({path: routeItem.path,name: routeItem.name,meta: routeItem.meta,})}},delRoute(state, params) {//删除tags路由项if (state.tagsRouter.length != 0) {let itemIndex = 0for (let i = 0; i < state.tagsRouter.length; i++) {let item = state.tagsRouter[i]if (state.tagsRouter[i].meta.menuKey === params.item.meta.menuKey) {//itemIndex = istate.tagsRouter.splice(i, 1)break}}//跳除后的跳转}},},actions: {doSomething(context, val) {//应用:this.$store.dispatch("doSomething",{})//提交mutations内的方法:context.commit("setUser",val)},},modules: {},
})

2 设置下路由信息,打开router/index.js

路由信息可跟据你的来,我只是截取了一下自己的实验内容,meta中可添加自己的信息

import Vue from 'vue'
import VueRouter from 'vue-router'import store from '@/store/index'
Vue.use(VueRouter)// 页面跳转时的进度条
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'NProgress.configure({easing: 'ease', // 动画方式speed: 500, // 递增进度条的速度showSpinner: false, // 是否显示加载icontrickleSpeed: 200, // 自动递增间隔minimum: 0.3, // 初始化时的最小百分比
})// routes设置根据你的项目来即可,我截取了一部分,可能会有错
const routes = [{path: '/',name: 'index',meta: { title: '首页', icon: 'home', menuKey: '1', menu: true },redirect: '/Dashboard/DashboardIndex',component: () =>import(/* webpackChunkName: "about" */ '../views/HomeView.vue'),},{path: '/Dashboard',name: 'Dashboard',meta: { title: 'Dashboard', icon: 'bar-chart', menuKey: '2' },component: () => import('../views/HomeView.vue'),children: [{path: 'DashboardIndex',name: 'DashboardIndex',meta: { title: 'DashboardIndex', icon: '', menuKey: '2.1' },component: () => import('@/views/dashboard/Dashboard.vue'),},],},{path: '/block',name: 'block',meta: { title: '链基础网络', icon: 'apartment', menuKey: '3' },component: () => import('../views/HomeView.vue'),children: [{path: 'BlockChainSetting',name: 'BlockChainSetting',meta: { title: '链配置', icon: '', menuKey: '3.1' },component: () => import('@/views/blockchain/BlockChainSetting.vue'),},{path: 'BlockChainSetUp',name: 'BlockChainSetUp',meta: { title: '链搭建', icon: '', menuKey: '3.2' },component: () => import('@/views/blockchain/BlockChainSetUp.vue'),},{path: 'BlockChainNetInfo',name: 'BlockChainNetInfo',meta: { title: '网络状态', icon: '', menuKey: '3.3' },component: () => import('@/views/blockchain/BlockChainNetInfo.vue'),},],}
]//NProgress 该组件是页面跳转时,页面上方出现的一条进度条,要安装下,npm install --save nprogressconst router = new VueRouter({mode: 'hash',base: process.env.BASE_URL,routes,
})router.beforeEach((to, from, next) => {// 每次切换页面时,调用进度条NProgress.start()if (to.meta.menuKey != undefined) {store.commit('addRoute', to)store.commit('setRouterTagActive', to)}next()
})//当路由进入后:关闭进度条
router.afterEach(() => {// 在即将进入新的页面组件前,关闭掉进度条NProgress.done()
})export default router

3 开发tags组件

<template><div class="menu-tags"><a-tag:class="['menu-tags_item', item.isActive ? 'item_active' : '']"closablev-for="(item, index) in data":key="item.name + index"@close="handleClose(item)"@click="handleSelect(item)"><span :class="item.isActive ? 'item_active' : ''">{{item.meta.title}}</span></a-tag></div>
</template><script>
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'export default {name: 'MenuTags',props: {},data() {return {data: [],}},computed: {...mapState({tagData() {return this.$store.state.tagsRouter},}),...mapGetters({getTagsRouterData: 'getTagsRouter', // 获取标签路由信息}),},// 定义引入的组件components: {},//变量监听watch: {},// 页面初始化created() {},// 页面DOM加载完成mounted() {let _this = this_this.init()},//离开页面时执行destroyed() {},watch: {},// 页面方法methods: {...mapMutations({mySetRouterTagActive: 'setRouterTagActive', // clickTotal 是mutation 里的方法,totalAlise是重新定义的一个别名方法,本组件直接调用这个方法}),init() {let _this = this_this.$set(_this, 'data', [])_this.$nextTick(() => {_this.$set(_this, 'data', _this.$store.state.tagsRouter)})},handleClose(item) {let _this = this//item.isActive = truelet tempData = [..._this.data]_this.$store.commit('delRoute', {item,isSameRoute: _this.$route.path == item.path,})if (tempData.length != 0 && _this.$route.path == item.path) {//跳转let gotoPath = ''for (let i = 0; i < tempData.length; i++) {if (tempData[i].path == item.path) {if (tempData[i + 1] != undefined) {gotoPath = tempData[i + 1].path} else if (tempData.length != 0) {gotoPath = tempData[0].path}break}}if (gotoPath != '') {_this.handleGoto(gotoPath)}}},handleSelect(item) {let _this = this//如果是当前页,则不跳if (item.name != _this.$route.name) {_this.$router.push({path: item.path,})_this.mySetRouterTagActive(item)_this.$nextTick(() => {_this.init()})}},handleGoto(path) {let _this = thisif (_this.$common.isNull(path)) {return false}_this.$router.push({path: path,})},},
}
</script><style lang="less" scoped>
.menu-tags {margin-left: 16px;.menu-tags_item {padding: 2px 10px;cursor: pointer;}.menu-tags_item:hover {color: #63d5ce;}.item_active {color: #63d5ce;}
}
</style>

4 引入到你的页面中,具体我不写了,你自己引

5 结果

其实,这个组件稍微有点麻烦,但原理就是,你如何处理每次点击的菜单项,把它存在哪,然后再渲染出来就行了。

vue 后台系统中多页面标签相关推荐

  1. Vue+ElementUi 项目中 将页面内容转为 Word文档下载

    Vue+ElementUi 项目中 将页面内容转为 Word文档下载 需要提前做好的现成模板(魔板个页面基本上相同的内容)-模板内有变量,替换成页面对应的数据 HTML页面: 转换的word 以下是正 ...

  2. IOS系统中H5页面实现摇一摇功能

    公司准备开年会了,年会活动用了一套别人的系统,根据测试,有些游戏的摇一摇功能在IOS上无法使用,为了修复该功能,踩了一些坑,特此记录如下: 1. 因为IOS系统的安全要求,项目必须是在https的域名 ...

  3. CMS系统中自定义模板标签、脚本的实现

    探讨问题的同胞们可以加QQ群:315309006 不少人对CMS很好奇,觉得CMS系统中为什么会出现各种不一样的标签,诸如<foreach *>.#if,有一些是#getArticle(& ...

  4. vue后台管理系统中,table表格页面使用mixins【混入自用】

    mixins文件夹中的view-module.js 在此js中写一些公用的data配置如:查询条件,分页属性等和table表格有关的data属性 在此js中写一些公用的methods方法如:查询,分页 ...

  5. vue后台项目中遇到的技术难点以及解决方案

    写在前面 马上到了金三银四的时间,很多公司开启了今年第一轮招聘的热潮,虽说今年是互联网的寒冬,但是只要对技术始终抱有热情以及有过硬的实力,即使是寒冬也不会阻挠你前进的步伐.在面试的时候,往往在二面,三 ...

  6. 如何构建一个vue登录系统之登录页面

    1. 在assets中新建一个css文件夹和imgs文件夹 2. 在src/views文件夹下新建一个Login.vue页面 3. 在src/main.js中引入全局公共样式文件style_publi ...

  7. Vue后台项目中权限管理

    传统的权限设计是对每个人进行单独的权限设置,但这种方式已经不适合目前企业的高效管控权限的发展需求,因为每个人都要单独去设置权限 RBAC的权限模型 基于角色的权限分配来解决,有中间层的角色 ,可以让权 ...

  8. vue H5项目中使用video标签无法播放视频,播放按钮也点不了,屏幕是黑的,解决方案

    原始代码 <video src="@/video/qiang.mp4" controls="controls"></video> 显示结 ...

  9. Vue实现app中搜索页面的炫酷搜索热词布局样式

    首先是效果图 可以自适应屏幕大小 可以每次刷新改变热词底色 在电脑显示如下 下面是实现过程 数据准备:原始数据为["**********"] 布局: 其中hotWords是上面的数 ...

最新文章

  1. java升序问题_JAVA并发理解之重排序问题
  2. T-SQL查询进阶--变量
  3. Google帮助IE浏览器实现对SVG支持
  4. SpringMVC+MyBatis 返回时间格式转换的解决方案
  5. Webpack 配置摘要
  6. 【大数据-第二期】java基础第五天作业
  7. 第一天docker入门
  8. 3DS烧录卡?ACE3DS PRO?这是个闹剧(关于此事的新闻集合)
  9. 人工智能优缺点_人工智能的优缺点
  10. 万物皆可编码:聊聊1~10这十个数字
  11. Scala使用ALS模型做推荐
  12. 计算机英语六级时间,计算机一级考试_6月英语六级报名时间
  13. 最近k8s遇到的一些问题
  14. 小实验:PC9与PC10连通的命令操作
  15. 查询-SPJ练习3参考答案
  16. Oracle 实验六:PL/SQL编程基础(1)
  17. Win10新加内存条后可用内存没增加解决方案
  18. win10恢复经典开始菜单_厌倦了默认的Win10开始菜单外观?这是自定义的方法
  19. 愚人节导入_您是否发现了这些愚人节愚人节的插科打??
  20. python3.4教程_Python教程(四)

热门文章

  1. 《安富莱嵌入式周报》第223期:2021.07.26--2021.08.01
  2. 字符串的练习 统计字符串中大写,小写,数字的个数 29
  3. 页面布局(1):淘宝首页
  4. Atmel Studio 编译no such file
  5. 使用 biblatex 进行参考文献管理
  6. MT6737模块编译方法
  7. ts快捷键 vscode_VS Code快捷键
  8. java privatekey输出字符串_根据字符串(String)生成公钥(PublicKey)和私钥(PrivateKey)对象...
  9. mac磁盘工具合并分区_如何使用Mac的磁盘工具对驱动器进行分区,擦除,修复,还原和复制
  10. 去吗?去啊!喜欢就不要再犹豫