vue

vue搭建后台,路由管理及页面缓存处理

2020-07-16  本文已影响0人  諍眼閉眼

实现功能

快速导航栏

1.缓存用户打开的页面
2.编辑 or 新增 后关闭当前页回到列表页并刷新列表
3.二次打开同路由的编辑页时判断 文章id是否相同(相同跳转,不同提示用户保存 or 新开一个窗口页面)

具体实现

router配置

{
                path: '/admin/user/index',
                name: 'admin-user-index',//这个name 必须与页面 name相同
                component: () => import('../views/admin/user/index.vue'),
                meta: {
                    title: "用户管理",
                    keepAlive: true,
                    type: "list",   // 全局路由判断是否是 list 页面
                    isBack:false    // 列表页判断编辑页面是否发生保存(编辑页控制状态 -> true :刷新列表页)
                }
            },{
                path: '/admin/user/edit/:id',
                name: 'admin-user-edit',
                component: () => import('../views/admin/user/edit.vue'),
                meta: {
                    title: "编辑用户",
                    keepAlive: true,
                    type: "edit",   // 全局路由判断是否是 edit 页面
                }
            },{
                path: '/admin/user/add',
                name: 'admin-user-add',
                component: () => import('../views/admin/user/add.vue'),
                meta: {
                    title: '新增用户',
                    keepAlive: true
                }
            }

excludeComponents(存入该数组内的页面name全部不缓存)
tips: router里面配置的name === 页面name 时才会生效

// 页面太多的建议 加上max 控制页面缓存数
 <keep-alive :exclude="excludeComponents">
          <router-view v-if="$route.meta.keepAlive"></router-view>
 </keep-alive>
 <router-view v-if="!$route.meta.keepAlive"></router-view>

vuex

state: {
        openTab:[],            // 所有打开的路由
        activeIndex:'/',       // 高亮路由(当前页)
        excludeComponents: [], // 取消已缓存的页面
    },

在mutations创建对应操作方法

1.添加打开的路由到openTab

add_tabs (state, data) {

            this.state.openTab.push(data);
            // 去除已强制不缓存的路由
            let index =  this.state.excludeComponents.indexOf(data.name)
            if (index > -1) {
                this.state.excludeComponents.splice(index, 1);
            }
        },
关闭tabs
 // 删除tabs (新开页面 保证页面处于可缓存状态)
        delete_tabs (state, route) {
            console.log(route)
            let index = 0;
            for (let option of state.openTab) {
                if (option.route === route) {
                    break;
                }
                index++;
            }
            // 删除标签  添加强制清除缓存
            if (this.state.excludeComponents.indexOf(this.state.openTab[index].name) == -1) {
                this.state.excludeComponents.push(this.state.openTab[index].name)
            }

            this.state.openTab.splice(index, 1);
        },
当前路由高亮
// 设置当前激活的tab
        set_active_index (state, index) {
            this.state.activeIndex = index;
        },
文章编辑保存后要删除 顶部快速导航标签 && 清除当前缓存的 编辑页面路由
  // 编辑页面   发生保存后删除tab
        edit_delete_tabs(state, name) {
            let index = 0;
            for (let option of state.openTab) {
                if (option.name === name) {
                    break;
                }
                index++;
            }
            // 删除标签  添加强制清除缓存
            this.state.excludeComponents.push(name)
            this.state.openTab.splice(index, 1);
        },

home页面(主路由)

import { mapState } from 'vuex'
computed:{
            ...mapState([
                'excludeComponents'
            ]),
        },
 mounted () {
            // 刷新时以当前路由做为tab加入tabs
            // 当前路由不是首页时,添加首页以及另一页到store里,并设置激活状态
            // 当当前路由是首页时,添加首页到store,并设置激活状态

            // 判断是否已经有了首页
            let openTab = this.$store.state.openTab;
            let type = false;
            for (let item of openTab) {
                if (item.route === "/") {
                    type = true
                }
            }
            if (!type) {
                this.$store.commit('add_tabs', {route: '/' , name: '首页'});
                type = false
            }

            if (this.$route.path !== '/') {
                /**
                  *openTab 内参数   route:页面路由  name: 页面name  titlt: 快捷标签上面显示的文章
                  */ 
                this.$store.commit('add_tabs', {route: this.$route.path , name: this.$route.name, title: this.$route.meta.title });
                this.$store.commit('set_active_index', this.$route.path);
            }

        },

列表页

 activated(){

            if(this.$route.meta.isBack){//判断列表是否需要更新
                // 如果是编辑页面 或 新增页面 发生了保存  则重新拉取列表
                this.getList();  // 获取文章列表
            }
        },
// tips 编辑页路由必须用params传参 (后面全局路由讲原因)
  this.$router.push({
                    name: "admin-user-edit",
                    params:{
                        id: row.userId ,
                    }
                })

编辑页

 // data内定义一个参数判断是否发生保存 isSave: false
 // 保存成功后
this.$message({
      message: '保存成功',
       type: 'success'
});
this.isSave= true;
 // === 清除tabs标签 ===
this.$store.commit('edit_delete_tabs', "admin-user-edit");
// 回到列表页
this.$router.push({
       path: "/admin/user/index"
})
// 路由卫士 改变isBack (告诉列表页 需要更新)
beforeRouteLeave(to,from,next){
            if(this.isSave){
                to.meta.isBack = true
            }
            next();
        }
//  新加文章页同理

mian.js配置全局路由

// 全局路由守卫 拦截所有路由
router.beforeEach((to, from, next) => {
// 每次离开编辑页是  isBack 状态切回 false 
    if (from.meta.type === "list") {
        from.meta.isBack = false
    }
    // 确定是列表页跳转到编辑-
    if (from.meta.type === "list" && to.meta.type === "edit") {

        let openTab = store.state.openTab;
        let type = false;
        // 找出已打开的页面里面有没有当前要打开的编辑页
        for (let item of openTab) {
            // --- 这里说下上面用params传参的原因  router里面带参 才能判断二次打开的编辑页是否是新的文字
            // 判断当前编辑页面是否已经打开  &&  因为路由带参 所以 路由并不全等
            if (item.name === to.name && item.route !== to.path) {
                type = true
            }
        }
        //  参数不同时 提示用户 已经有打开的编辑页了
        if (type) {
            type = false;
            app.$confirm('你还有未关闭的编辑页面', '提示', {
                confirmButtonText: '新开页面',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                window.open( "/#" + to.path)
            }).catch(() => {

            });
        } else {
            next();
        }

    } else {
        next()
    }


})

快捷标签组件

<template>
    <div class="box">
        <div class="tag">
            <el-tag
                    v-for="tag in openTab"
                    :key="tag.name"
                    closable
                    @click="tabClick(tag.route)"
                    @close="tabRemove(tag.route)"
                    :type="activeIndex == tag.route ? 'success' : 'info'">
                {{ tag.title ? tag.title : tag.name}}
            </el-tag>
        </div>
    </div>

</template>

<script>
    export default {
        watch: {
            '$route'(to,from){
                //判断路由是否已经打开
                //已经打开的 ,将其置为active
                //未打开的,将其放入队列里

                let flag = false;
                for(let item of this.openTab){
                    if(item.name === to.name){
                        this.$store.commit('set_active_index',to.path)
                        flag = true;
                        break;
                    }
                }
                if(!flag){

                    this.$store.commit('add_tabs', {route: to.path, name: to.name, title: to.meta.title});
                    this.$store.commit('set_active_index', to.path);
                }
            }
        },
        methods: {
            // ------------------------------ 路由 ---------------------------------------
            //tab标签点击时,切换相应的路由
            tabClick(path){
                if (path != this.activeIndex) {
                    this.$router.push({path: path});
                }
            },
            //移除tab标签
            tabRemove(targetName){
                console.log("tabRemove",targetName);// ------------- 这里做编辑保存后 关闭标签
                //首页不删
                if(targetName == '/'){
                    return
                }
                console.log(targetName)
                this.$store.commit('delete_tabs', targetName);
                if (this.activeIndex === targetName) {
                    // 设置当前激活的路由
                    if (this.openTab && this.openTab.length >= 1) {
                        // console.log('=============',this.openTab[this.openTab.length-1].route)
                        this.$store.commit('set_active_index', this.openTab[this.openTab.length-1].route);
                        this.$router.push({path: this.activeIndex});
                    } else {
                        this.$router.push({path: '/'});
                    }
                }
            },

        },
        computed: {
            openTab () {
                return this.$store.state.openTab;
            },
            activeIndex:{
                get () {
                    return this.$store.state.activeIndex;
                },
                set (val) {
                    this.$store.commit('set_active_index', val);
                }
            }
        },
    }
</script>

<style scoped lang="less">
    .box {
        width: calc(100% - 40px);
        height: 47px;
        border-radius: 5px;
        overflow: hidden;
        background-color: #fff;
        box-shadow: 0px 0px 10px 3px #eee;
        position: absolute;
        left: 20px;
        bottom: 0;
        .tag {
            padding: 6px 6px 6px 0;
            white-space: nowrap;
            overflow: hidden;
            overflow-x: scroll;
            .el-tag {
                margin-left: 6px;
                &:hover {
                    cursor: pointer;
                }
            }
        }
    }

</style>
上一篇 下一篇

猜你喜欢

热点阅读