antd vue pro (vue 2.x) 多页签详细操作

antd vue pro 多页签配置操作,具体操作如下。

1.引入 tagviews文件

  在 store/modules 中创建 tagviews.js ,复制一下代码到文件中保存

const state = {visitedViews: [],cachedViews: []
}const mutations = {ADD_VISITED_VIEW: (state, view) => {if (state.visitedViews.some(v => v.path === view.path)) returnstate.visitedViews.push(Object.assign({}, view, {title: view.meta.title || 'no-name'}))},ADD_CACHED_VIEW: (state, view) => {if (state.cachedViews.includes(view.name)) returnif (view.meta && view.meta.isCache) {state.cachedViews.push(view.name)}},DEL_VISITED_VIEW: (state, view) => {for (const [i, v] of state.visitedViews.entries()) {if (v.path === view.path) {state.visitedViews.splice(i, 1)break}}},DEL_CACHED_VIEW: (state, view) => {const index = state.cachedViews.indexOf(view.name)index > -1 && state.cachedViews.splice(index, 1)},DEL_OTHERS_VISITED_VIEWS: (state, view) => {state.visitedViews = state.visitedViews.filter(v => {return v.meta.affix || v.path === view.path})},DEL_OTHERS_CACHED_VIEWS: (state, view) => {const index = state.cachedViews.indexOf(view.name)if (index > -1) {state.cachedViews = state.cachedViews.slice(index, index + 1)} else {state.cachedViews = []}},DEL_ALL_VISITED_VIEWS: state => {// keep affix tagsconst affixTags = state.visitedViews.filter(tag => tag.meta.affix)state.visitedViews = affixTags},DEL_ALL_CACHED_VIEWS: state => {state.cachedViews = []},UPDATE_VISITED_VIEW: (state, view) => {for (let v of state.visitedViews) {if (v.path === view.path) {v = Object.assign(v, view)break}}},DEL_RIGHT_VIEWS: (state, view) => {const index = state.visitedViews.findIndex(v => v.path === view.path)if (index === -1) {return}state.visitedViews = state.visitedViews.filter((item, idx) => {if (idx <= index || (item.meta && item.meta.affix)) {return true}const i = state.cachedViews.indexOf(item.name)if (i > -1) {state.cachedViews.splice(i, 1)}return false})},DEL_LEFT_VIEWS: (state, view) => {const index = state.visitedViews.findIndex(v => v.path === view.path)if (index === -1) {return}state.visitedViews = state.visitedViews.filter((item, idx) => {if (idx >= index || (item.meta && item.meta.affix)) {return true}const i = state.cachedViews.indexOf(item.name)if (i > -1) {state.cachedViews.splice(i, 1)}return false})}
}const actions = {addView ({dispatch}, view) {dispatch('addVisitedView', view)dispatch('addCachedView', view)},addVisitedView ({commit}, view) {commit('ADD_VISITED_VIEW', view)},addCachedView ({commit}, view) {commit('ADD_CACHED_VIEW', view)},delView ({dispatch,state}, view) {return new Promise(resolve => {dispatch('delVisitedView', view)dispatch('delCachedView', view)resolve({visitedViews: [...state.visitedViews],cachedViews: [...state.cachedViews]})})},delVisitedView ({commit,state}, view) {return new Promise(resolve => {commit('DEL_VISITED_VIEW', view)resolve([...state.visitedViews])})},delCachedView ({commit,state}, view) {return new Promise(resolve => {commit('DEL_CACHED_VIEW', view)resolve([...state.cachedViews])})},delOthersViews ({dispatch,state}, view) {return new Promise(resolve => {dispatch('delOthersVisitedViews', view)dispatch('delOthersCachedViews', view)resolve({visitedViews: [...state.visitedViews],cachedViews: [...state.cachedViews]})})},delOthersVisitedViews ({commit,state}, view) {return new Promise(resolve => {commit('DEL_OTHERS_VISITED_VIEWS', view)resolve([...state.visitedViews])})},delOthersCachedViews ({commit,state}, view) {return new Promise(resolve => {commit('DEL_OTHERS_CACHED_VIEWS', view)resolve([...state.cachedViews])})},delAllViews ({dispatch,state}, view) {return new Promise(resolve => {dispatch('delAllVisitedViews', view)dispatch('delAllCachedViews', view)resolve({visitedViews: [...state.visitedViews],cachedViews: [...state.cachedViews]})})},delAllVisitedViews ({commit,state}) {return new Promise(resolve => {commit('DEL_ALL_VISITED_VIEWS')resolve([...state.visitedViews])})},delAllCachedViews ({commit,state}) {return new Promise(resolve => {commit('DEL_ALL_CACHED_VIEWS')resolve([...state.cachedViews])})},updateVisitedView ({commit}, view) {commit('UPDATE_VISITED_VIEW', view)},delRightTags ({commit}, view) {return new Promise(resolve => {commit('DEL_RIGHT_VIEWS', view)resolve([...state.visitedViews])})},delLeftTags ({commit}, view) {return new Promise(resolve => {commit('DEL_LEFT_VIEWS', view)resolve([...state.visitedViews])})}
}export default {namespaced: true,state,mutations,actions
}

2. tagviews文件引用

 (1)在 store/getters.js 引入

const getters = {.....
// 下方两句关键代码visitedViews: state => state.tagsView.visitedViews,cachedViews: state => state.tagsView.cachedViews
}export default getters

 (2)在 store/index.js 引入

....其他代码
// 关键代码
import tagsView from './modules/tagviews'.... 其他代码
export default new Vuex.Store({modules: {app,user,permission,// 关键代码tagsView},state: {},mutations: {},actions: {},getters
})

3. 更改routeview.vue 文件

 在 layouts/RouteView.vue 直接替换成以下代码

<template><keep-alive :include="cachedViews"><router-view :key="key" /></keep-alive>
</template>
<script>
export default {name: 'RouteView',computed: {cachedViews () {return this.$store.state.tagsView.cachedViews},key () {return this.$route.fullPath}},props: {keepAlive: {type: Boolean,default: true}},data () {return {}}}
</script>

4.更改mutiltable.vue文件

components/MultiTab/MultiTab.vue 中直接替换以下代码

<script>
import events from './events'export default {name: 'MultiTab',data () {return {fullPathList: [],pages: [],activeKey: '',newTabIndex: 0}},created () {// bind eventevents.$on('open', (val) => {console.log('table_open', val)if (!val) {throw new Error(`multi-tab: open tab ${val} err`)}this.activeKey = val}).$on('close', (val) => {if (!val) {this.closeThat(this.activeKey)return}this.closeThat(val)}).$on('rename', ({ key, name }) => {console.log('rename', key, name)try {const item = this.pages.find((item) => item.path === key)item.meta.customTitle = namethis.$forceUpdate()} catch (e) {}})this.pages.push(this.$route)this.fullPathList.push(this.$route.fullPath)this.selectedLastPath()},methods: {onEdit (targetKey, action) {this[action](targetKey)},remove (targetKey) {const newVal = this.getPage(targetKey)this.pages = this.pages.filter((page) => page.fullPath !== targetKey)this.fullPathList = this.fullPathList.filter((path) => path !== targetKey)if (newVal != null) {this.$store.dispatch('tagsView/delView', newVal)}// 判断当前标签是否关闭,若关闭则跳转到最后一个还存在的标签页if (!this.fullPathList.includes(this.activeKey)) {this.selectedLastPath()}},selectedLastPath () {this.activeKey = this.fullPathList[this.fullPathList.length - 1]},getPage (targetKey) {const newVal = this.pages.filter((c) => c.fullPath === targetKey)return newVal.length > 0 ? newVal[0] : null},// content menucloseThat (e) {// 判断是否为最后一个标签页,如果是最后一个,则无法被关闭if (this.fullPathList.length > 1) {this.remove(e)} else {this.$message.info('这是最后一个标签了, 无法被关闭')}},closeLeft (e) {const currentIndex = this.fullPathList.indexOf(e)if (currentIndex > 0) {this.fullPathList.forEach((item, index) => {if (index < currentIndex) {this.remove(item)}})} else {this.$message.info('左侧没有标签')}},closeRight (e) {const currentIndex = this.fullPathList.indexOf(e)if (currentIndex < this.fullPathList.length - 1) {this.fullPathList.forEach((item, index) => {if (index > currentIndex) {this.remove(item)}})} else {this.$message.info('右侧没有标签')}},closeAll (e) {const currentIndex = this.fullPathList.indexOf(e)this.fullPathList.forEach((item, index) => {if (index !== currentIndex) {this.remove(item)}})},refreshPage (e) {const currentIndex = this.fullPathList.indexOf(e)this.fullPathList.forEach((item, index) => {if (index === currentIndex) {let newVal = this.getPage(item)if (newVal != null) {const { path, query, matched } = newValmatched.forEach((m) => {if (m.components && m.components.default && m.components.default.name) {if (!['Layout', 'ParentView'].includes(m.components.default.name)) {newVal = { name: m.components.default.name, path: path, query: query }}}})console.log('refreshpage', newVal)this.$store.dispatch('tagsView/delCachedView', newVal).then((res) => {const { path, query } = newValthis.$router.replace({path: '/redirect' + path,query: query})})}}})},closeMenuClick (key, route) {this[key](route)},renderTabPaneMenu (e) {return (<a-menu{...{on: {click: ({ key, item, domEvent }) => {this.closeMenuClick(key, e)}}}}><a-menu-item key="closeThat">关闭当前标签</a-menu-item><a-menu-item key="closeRight">关闭右侧</a-menu-item><a-menu-item key="closeLeft">关闭左侧</a-menu-item><a-menu-item key="closeAll">关闭全部</a-menu-item><a-menu-item key="refreshPage">刷新标签</a-menu-item></a-menu>)},// renderrenderTabPane (title, keyPath) {const menu = this.renderTabPaneMenu(keyPath)return (<a-dropdown overlay={menu} trigger={['contextmenu']}><span style={{ userSelect: 'none' }}>{title}</span></a-dropdown>)},addtags () {const newVal = this.$routethis.$store.dispatch('tagsView/addView', newVal)}},mounted () {this.addtags()},watch: {$route: function (newVal) {this.activeKey = newVal.fullPaththis.addtags()if (this.fullPathList.indexOf(newVal.fullPath) < 0) {this.fullPathList.push(newVal.fullPath)this.pages.push(newVal)}},activeKey: function (newPathKey) {this.$router.push({ path: newPathKey })}},render () {const {onEdit,$data: { pages }} = thisconst panes = pages.map((page) => {return (<a-tab-panestyle={{ height: 0 }}tab={this.renderTabPane(page.meta.customTitle || page.meta.title, page.fullPath)}key={page.fullPath}closable={pages.length > 1}></a-tab-pane>)})return (<div class="ant-pro-multi-tab"><div class="ant-pro-multi-tab-wrapper"><a-tabshideAddtype={'editable-card'}v-model={this.activeKey}tabBarStyle={{ background: '#FFF', margin: 0, paddingLeft: '16px', paddingTop: '1px' }}{...{ on: { edit: onEdit } }}>{panes}</a-tabs></div></div>)}
}
</script>

5.生成路由地方配置,本文路由生成在 permission.js中,具体位置看项目

 注意事项:

        1、每个路由的name必须跟页面内的name一致,否则不会缓存

        2、路由当中的isCache 是控制多页签是否缓存重要属性(可自己控制是否缓存开关)

至此流程结束,多页签功能完成

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/8112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Element-ui-vue3-前端界面开发-配置-编辑main.js-nodejs基础语法-vue3-html模板语法-vue文件编译

前端配置 1.下载nodejs 18 lts2.配置nodejs和安装vue3.vue调试技巧3.1.debugger3.2.vue devtools4.编辑main.js5.nodejs基础语法5.1.import5.1.1.导入单个模块或组件5.1.2.导入整个模块或库5.1.3.导入默认导出5.1.4.导入 css文件5.1.5.导入模块和组件5.2.export5.2.1.命名导出5…

数学建模资料|历年数维杯数学建模竞赛真题及获奖论文汇总

2024年第九届数维杯大学生数学建模挑战赛:2024年5月10日08:00-5月13日09:00举行,为了更好的帮助参赛同学了解竞赛的赛制及赛题特点,数乐君今天给大家整理了历年数维杯国赛真题及优秀论文,方便同学们赛前巩固训练,掌握解题方法,提高获奖率。 2023年数维杯国赛真题(ABC题…

如何在没有备份的情况下恢复 Mac 上丢失的数据

如果您因意外删除、错误格式化硬盘或文件损坏而丢失了重要的、感伤的文件、照片或音乐&#xff0c;那么这可能会令人非常痛苦。幸运的是&#xff0c;您有几个选择。 您的 Mac 位于数字宇宙的中心。您可能会在上面留下照片和视频形式的记忆&#xff0c;以及来自您不再见面的朋友…

前端如何设置div可滚动,且设置滚动条颜色

在前端中&#xff0c;设置 div 为可滚动并通过 CSS 自定义滚动条的颜色并不是所有浏览器都直接支持的功能&#xff0c;因为滚动条的样式在很大程度上取决于操作系统和浏览器的默认样式。然而&#xff0c;你可以使用某些 CSS 属性来尝试自定义滚动条的外观&#xff0c;这些属性在…

C语言 | Leetcode C语言题解之第75题颜色分类

题目&#xff1a; 题解&#xff1a; void swap(int *a, int *b) {int t *a;*a *b, *b t; }void sortColors(int *nums, int numsSize) {int p0 0, p2 numsSize - 1;for (int i 0; i < p2; i) {while (i < p2 && nums[i] 2) {swap(&nums[i], &num…

Linux系统 -- 创建systemd服务单元 Python 程序在系统启动时自动启动,并持续运行。

1. 创建一个名为 model_ai.service 的文件&#xff0c;并将其放置在 /etc/systemd/system/ 目录中。 2. 命令创建和编辑文件 sudo vim /etc/systemd/system/model_ai.service 3. 在打开的编辑器中&#xff0c;添加以下内容&#xff1a; [Unit] DescriptionModel AI Python S…

QT实现Home框架的两种方式

在触摸屏开发QT界面一般都是一个Home页面&#xff0c;然后button触发进入子页面显示&#xff0c;下面介绍这个home框架实现的两种方式&#xff1a; 1.方式一&#xff1a;用stackedWidget实现 &#xff08;1&#xff09;StackedWidget控件在Qt框架中是一个用于管理多个子窗口或…

文件夹名称大小写转换:名称首字母转大写,一种高效的文件管理方法

在日常生活和工作中&#xff0c;电脑文件夹的管理对于提高工作效率和文件检索的便捷性至关重要。文件夹名称的命名规则直接影响到文件组织的有序性和查找的速度。其中&#xff0c;将文件夹名称的首字母转换为大写是一种简单而高效的管理方法&#xff0c;下面我们就来详细探讨实…

Linux提示:mount: 未知的文件系统类型“ntfs”

mount: 未知的文件系统类型“ntfs” 在Linux系统中&#xff0c;如果遇到“mount: 未知的文件系统类型‘ntfs’”的错误&#xff0c;这通常意味着您的系统没有安装支持NTFS文件系统的软件。为了挂载NTFS文件系统&#xff0c;您需要安装ntfs-3g软件包。以下是如何在不同Linux发行…

免费ChatGPT转接地址免费ChatGPT直连地址以及使用方法

依赖环境 Python3.8以上环境 安装依赖包 pip install openai 使用方法-Python #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 2024-05-08 8:56 # Author : Jack # File : chat_direct""" chat_direct """ import openai from…

Golang | Leetcode Golang题解之第76题最小覆盖子串

题目&#xff1a; 题解&#xff1a; func minWindow(s string, t string) string {ori, cnt : map[byte]int{}, map[byte]int{}for i : 0; i < len(t); i {ori[t[i]]}sLen : len(s)len : math.MaxInt32ansL, ansR : -1, -1check : func() bool {for k, v : range ori {if c…

为什么 ChatGPT 不火了?

不火了是有原因的&#xff0c;下面我来从大部分人拿到 ChatGPT 之后的两大痛点开始讲起&#xff1a; 很多朋友拿到 ChatGPT 后的第一个痛点就是&#xff1a;用的不好 你经常会感觉到 ChatGPT 回答的好空&#xff0c;没有太多参考价值。 而第二个痛点则是&#xff1a;无处去用…

Vue按照顺序实现多级弹窗(附Demo)

目录 前言1. 单个弹窗2. 多级弹窗 前言 强化各个知识点&#xff0c;以实战融合&#xff0c;以下两个Demo从实战提取 1. 单个弹窗 部署按钮框以及确定的方法即可 截图如下所示&#xff1a; 以下Demo整体逻辑如下&#xff1a; 点击“生成周月计划”按钮会触发showWeekPlanDia…

uniapp日期区间选择器

uniapp日期区间选择器 在 uniapp 中创建一个简单的自定义日期范围的日期区间选择器&#xff1a; - 限制有效日期范围开始日期为 2024-01-01&#xff0c;结束日期为当日&#xff1b; - 默认日期区间为当日向前计算的7日区间&#xff1b; - 选择开始时间后&#xff0c;判断不可大…

苹果删除的短信怎么恢复?这里有4个恢复技巧

手机短信已成为我们日常沟通中不可或缺的一部分&#xff0c;其中包含了与家人、朋友的温馨对话&#xff0c;以及与工作伙伴的重要信息。然而&#xff0c;有时我们可能会因为误操作或其他原因不小心删除了重要的短信。请别担心&#xff0c;本文将为您详细介绍删除的短信怎么恢复…

推荐5个免费的国内平替版GPT

提起AI&#xff0c;大家第一个想到的就是GPT。 虽然它确实很厉害&#xff0c;但奈何于我们水土不服&#xff0c;使用门槛有些高。 不过随着GPT的爆火&#xff0c;现在AI智能工具已经遍布到各行各业了&#xff0c;随着时间的推移&#xff0c;国内的AI工具也已经“百花盛放”了…

Python机器学习手册:从预处理到深度学习的实际解决方案

书籍&#xff1a;Machine Learning with Python Cookbook: Practical Solutions from Preprocessing to Deep Learning 作者&#xff1a;Kyle Gallatin&#xff0c;Chris Albon 出版&#xff1a;OReilly Media 书籍下载-《Python机器学习手册&#xff1a;从预处理到深度学习…

数据结构学不会?数据结构可视化网站来了

目录 前言 图码网站 算法可视化 算法编辑器 数据结构全书 数据结构课程 总结 前言 数据结构与算法在计算机的学习中应该是许多小白最头疼的东西&#xff0c;明明听的时候那么容易&#xff0c;为什么转换成代码就那么抽象呢&#xff1f; 有没有一个网站可以数据结构与算…

【OceanBase诊断调优】—— 磁盘性能问题导致卡合并和磁盘写入拒绝排查

适用版本 OceanBase 数据库 V3.x、V4.x 版本。 问题现象 OceanBase 集群合并一直未完成&#xff0c;同时 tsar 和 iostat 显示从凌晨 2:30 开始磁盘使用率一直是 100%。怀疑合并导致 IO 上升&#xff0c;IO 可能存在问题&#xff0c;observer.log 的确有大量报错 disk is hu…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 5月8日,星期三

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年5月8日 星期三 农历四月初一 1、 我国将对法国等12国免签政策延长至2025年底&#xff0c;旅游平台加码布局入境游。 2、 财政部&#xff1a;下拨1582亿元&#xff0c;提高义务教育阶段家庭经济困难学生补助标准。 3、 4月…