vue搭建后台,路由管理及页面缓存处理
2020-07-16 本文已影响0人
諍眼閉眼
实现功能
![](https://img.haomeiwen.com/i9306050/c468010d8fb3ed0e.png)
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>