vue实现多标签保持页面管理系统

此篇文章主要介绍如何利用vuex实现多标签保持页面管理功能,效果如图所示:
在这里插入图片描述
希望本篇文章对有需要实现类似功能的小伙伴,有一点点借鉴效果,好了废话不多说一步一步来介绍。

运用的Vue技术点参考

关于vue-router应用参考: https://blog.youkuaiyun.com/sunshouyan/article/details/107016023
关于vuex应用参考:https://blog.youkuaiyun.com/sunshouyan/article/details/107020699
vue的components组件参数配置以及keep-alive的综合运用;

多标签保持功能实现具体效果
  • 实现多标签页面打开;
  • 实现按需求页面内容缓存;
  • 实现浏览器刷新标签依然保持;
  • 实现标签和菜单联动定位;
  • 实现动态参数标签页面;
  • 实现标签打开溢出鼠标滚轮滚动查看;
1. 平台整体框架搭建

首先具体实现功能之前,我们先对自己想要实现的前端交互样式有一个简单的规划,当然这个可以根据具体设计UI图调整,但基本思路不会变。
如下图:
在这里插入图片描述
a、顶部是公用的头部展示区域;
b、左侧是权限菜单展示区域;
c、右侧上部分是多标签展示区域;
d、右侧下部分是动态路由页面切换区域;

操作链:
正向操作:b菜单操作->产生c和d
反向操作:c标签操作-> 联动b和d

根据以上交互思路,我们简单把主框架拆分成不同的小组件,组成整体布局Layout;
Layout组成包括:
index.vue // 框架主入口组件
navBar.vue // 左侧动态菜单展示组件
tagNav.vue // 标签展示和操作组件
scrollBar.vue // 标签打开过多的情况,负责标签滚动计算和滚动

Layout / index.vue代码结构如下:

<template>
    <div class="layout">
        <!-- 公用头部区域 -->
        <div class="layout-top">
            <div class="logo">{
   
   {
   
   sysName}}</div>
            <div class="info">
                <span><i class="el-icon-s-custom"></i> {
   
   {
   
   userName}}</span>
                <span><i class="el-icon-bell"></i> 消息</span>
                <span><i class="el-icon-setting"></i> 设置</span>
                <span @click="closeAllTags"><i class="el-icon-delete"></i> 清空标签</span>
            </div>
        </div>
         <div class="layout-main">
            <!-- 动态菜单展示区域 -->
            <div class="layout-main-left">
                <NavBar :isCollapse='menuCollapse'></NavBar>
            </div> 
            <div class="layout-main-right">
                <!-- 标签展示区域 -->
                <div class="right-nav">
                   <TagNav></TagNav>
                </div>
                <!-- 标签动态路由区域 -->
                 <div class="right-inner">
                    <keep-alive :include="tagNavList">
                        <router-view></router-view>
                    </keep-alive>
                </div>
            </div>
        </div> 
    </div>
</template>
<script>
/**
 * @description 框架入口组件
 * @author      sunsy
 * @createTime  2020/07/11
 */
import NavBar from "./navBar"
import TagNav from "./tagNav";
export default {
   
   
    name: "layout",
    components: {
   
   
        TagNav,
        NavBar,
    },
    data() {
   
   
        return {
   
   
            // 系统名称信息
            sysName: "砖农吃瓜平台",
            // 登录的用户信息
            userName: "sunsy",
            // 菜单栏是否是展开状态
            menuCollapse: false,
        };
    },
    computed: {
   
   
        // 读取缓存的标签页面
        tagNavList() {
   
   
            return this.$store.state.tagNav.cachedPageName;
        }
    },
    methods: {
   
   
        // 清空之前缓存的所有标签以及缓存数据
        closeAllTags() {
   
   
            this.$store.dispatch('tagNav/clearAllTag');
        }
    },
    created() {
   
   
        //let user = localStorage.getItem("userInfo");
        //if (user) {
   
   
        //    this.userInfo = JSON.parse(user);
       // }
    },
}

准备好主框架后,我们需要先准备动态菜单和路由,因为只有了菜单和路由的基础,才能产生我们的标签数据。

2. 准备动态菜单数据和路由配置

本文中示例项目中所有的请求都采用Mock模拟后端返回,所以如果有按照本文流程测试的小伙伴记得安装Mock依赖;

a. 菜单准备

mock/navlist.js数据格式如下:
在这里插入图片描述
需要注意点:

菜单里存在显性菜单和隐性菜单两种:
1.显性菜单指菜单名称需要在菜单列表显示出来;
2.隐性菜单指菜单名称不需要在菜单列表展示出来,但是又属于用户权限里的一个,一般出现在详情二级页面的访问的情况;
3.在以上Json数据中,type:0 指显性菜单; type:2 指隐性菜单; 可以根据自己情况配置测试。
ps: 其实还有一种菜单权限是指操作菜单type:1;(例如新增、删除、编辑按钮)但是这个牵扯到用户权限系统的时才使用,演示项目并不牵扯到用户权限,所以本文中不做具体介绍。

动态菜单采取了vuex状态管理,首次请求本地做缓存,以提高访问性能和速度。
strore/modules/auth/index.js文件代码:

/**
 * @description 用户菜单权限状态管理模块
 * @author      sunsy
 * @createTime  2019/08/19
 */
import axios from '@/util/ajax'
const state = {
   
   
    navList: [],
}

const mutations = {
   
   
    setNavList: (state, data) => {
   
   
        state.navList = data
    },
}

const actions = {
   
   
    // 获取该用户的菜单列表
    getNavList({
   
    commit }) {
   
   
        return axios.get({
   
   
            url: '/api/menu',
            data:''
        }).then((res) => {
   
   
            let data = res.data || [];
            commit("setNavList", data);
        });
    },
    // 将菜单列表扁平化形成权限列表
    getPermissionList({
   
    state }) {
   
   
        return new Promise((resolve) => {
   
   
            let permissionList = []
            // 将菜单数据扁平化为一级
            function flatNavList(arr) {
   
   
                for (let v of arr) {
   
   
                    if (v.children && v.children.length) {
   
   
                        flatNavList(v.children)
                    } else {
   
   
                        permissionList.push(v)
                    }
                }
            }
            flatNavList(state.navList)
            resolve(permissionList)
        })
    },
    // 清空缓存的菜单数据
    clearAllMenu: ({
   
    commit }) => {
   
   
        commit("setNavList", []);
    },
}

export default {
   
   
    namespaced: true,
    state,
    mutations,
    actions
}
b. 路由配置

模拟准备好菜单数据后,接下来就是准备菜单对应的组件以及路由和菜单映射关系配置。
router/staticRoute.js文件:在这里插入图片描述
需要注意点:

1.需要用标签打开的路由,组件加载都是基于layout组件,所以组件引入的时候父组件记得配置为layout;
2.不需要标签打开的路由,不需要如此配置;

c. 菜单和路由初始化

菜单和对应的组件配置准备好后,接下来就是初始化路由的时候引入菜单并做相关的业务操作处理。
router/index.js 文件代码:

import Vue from 'vue'
import VueRouter from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import store from '../store'
import staticRoute from './staticRoute'
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值