vue2使用keep-alive缓存已打开过的菜单,使用el-tabs展示面包屑路由。

需求:

点击左侧菜单栏,面包屑实时更新,如果所点击菜单在面包屑中存在,需要缓存,不存在重新加载,面包屑tab切换需要缓存,关闭one-tab更新tabslist。
keepalive只支持二级路由,多级路由需要扁平化处理。

使用vuex,vue-class-component类组件封装,自行转换。

面包屑tabs组件

components/CommonTab.vue
<template>
    <div class="tabs" ref="tags">
        <el-tabs v-model="currentName" type="card" @edit="handleTabsEdit" @tab-click="handleTabClick">
            <el-tab-pane :key="tag.name" v-for="tag in tags" :closable="tag.name === ('首页' || '首頁') ? false : true" :label="tag.meta.title" :name="tag.meta.title"> </el-tab-pane>
        </el-tabs>
    </div>
</template>
<script lang="ts">
import { Vue, Component, Mixins, Watch, Prop } from 'vue-property-decorator'; 

@Component
export default class CommonTab extends Vue {
    tags: any = [];
    editableTabsValue: any = '';
    currentName: any = '';
    async mounted() {
        this.tags = this.$store.state.tabsList;
    }
    @Watch('$route.meta.title', { deep: true })
    onTagsChange(newVal: any, oldVal: any) {
        if (newVal !== oldVal) {
            this.currentName = newVal;
        }
    }
    handleTabsEdit(targetName: any, action: any) {
        if (action === 'remove') {
            // tags
            let result = this.tags.findIndex((item: any) => item.meta.title === targetName);
            this.handleClose(this.tags[result], result);
        }
    }
    handleTabClick(tab: any) {
        let result = this.tags.findIndex((item: any) => item.meta.title === this.currentName);
        this.changeMenu(this.tags[result]);
    }
    handleClose(tag: any, index: any) {
        let length = (this as any).tags.length - 1;
        // vuex调方法的另一种写法
        this.$store.commit('closeTab', tag);
        // 如果关闭的标签不是当前路由的话,就不跳转
        if (tag.name !== (this as any).$route.name) {
            return;
        }
        // 关闭的标签是最右边的话,往左边跳转一个
        if (index === length) {
            (this as any).$router.push({ path: (this as any).tags[index - 1].path });
        } else {
            // 否则往右边跳转
            (this as any).$router.push({ path: (this as any).tags[index].path });
        }
    }
    // 选择标签跳转路由
    changeMenu(item: any) {
        (this as any).$router.push(item.path);
        (this as any).$store.commit('selectMenu', item);
    }
}
</script>
<style lang="scss" scope>
.tabs {
    // line-height: 20px;
    margin-left: 18px;
    text-align: center;
    position: relative;
}
.el-tabs {
    color: #000;
    border-radius: 17px;
    // border: 1px solid red;
    left: 0px;
    top: 0px;
    height: 32px;
    position: relative;
}
.el-tabs__item {
    // border: 1px solid red;
    border-radius: 5px;
    padding: 0 5px;
    margin-left: 5px;
    background: white;
    line-height: 28px;
    height: 28px;
    font-size: 12px;
}
.el-tabs__nav-next,
.el-tabs__nav-prev {
    line-height: 28px;
}
 
.el-tabs__item.is-active {
    background: #409eff;
    color: white !important;
    padding-right: 5px !important;
    padding-left: 5px !important; 
} 
</style>

vuex

import Vue from 'vue';
import Vuex from 'vuex';

let availButtons = new Set();
export default new Vuex.Store({
    modules: {
        // 把 store/modules下的文件引入
    },
    state: {
        buttons: availButtons,
        currentMenu: null,
        menu: [],
        tabsList: [
            {
                path: '/',
                name: 'Profile',
                icon: 'home',
                meta: {
                    title: '首页'
                }
            }
        ],
        keepAliveList: ['Profile']
    },
    mutations: {
        // 选择标签 选择面包屑
        selectMenu(state, val) {
            console.log({ val });
            if (val.path === '/') {
                state.currentMenu = null;
            } else {
                state.currentMenu = val;
                let result = state.tabsList.findIndex(item => item.name === val.name);
                if (result === -1) {
                    state.tabsList.push(val);
                }
            }
        },
        closeTab(state, val) {
            let result = state.tabsList.findIndex(item => item.name === val.name);
            state.tabsList.splice(result, 1);
            state.keepAliveList = [];
            state.tabsList.forEach(item => {
                state.keepAliveList.push(item.name);
            });
        },
        updateKeepList(state, val) {
            let index = state.keepAliveList.findIndex((item: any) => item.name === val.name);
            if (index === -1) {
                state.keepAliveList.push(val.name);
            }
        }
    },
    actions: {},
    getters: {}
});

Home.vue(控制router-view的主页面)

<transition>
    <keep-alive :include="$store.state.keepAliveList">
        <router-view> </router-view>
    </keep-alive>
</transition>
点击菜单触发事件:
在el-menu-item中@click
clickMenu(item: any) {
        this.$store.commit('selectMenu', this.$route);
        this.$store.commit('updateKeepList', this.$route);
    }

route结构配置

{
        path: '/login',
        component: Login
    },
    {
        path: '/',
        component: Home,
        children: [
            {
                name: 'profile',
                path: '/',
                component: Profile,
                meta: {
                    title: '首页'
                }
            },
            {
                name: 'Users',
                path: '/users',
                component: Users,
                meta: {
                    title: '用户管理'
                }
            },
            {
                name: 'Roles',
                path: '/roles',
                component: Roles,
                meta: {
                    title: '角色管理'
                }
            }
            ]}

缺点:默认刷新之后进入Profile页面,没有动态更新刷新。可以在Home中mouted中自定义传值当前router。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值