在开发不少管理系统过程之中,常遇到这种需求,须要对打开路由页面进行缓存,而后在系统页眉提供方便查阅的tab标签进行切换以及对已经缓存页面进行数据刷新和清除数据操做。具体演示以下图所示:javascript
在上面演示中实现了相似window tab
标签页效果,会对当前数据进行缓存。在浏览器中实现对路由页面的缓存能够减小接口请求,也方便了用户来回切换想搜索的数据列表。vue
Vue
提供的keep-alive
API实现对路由组件的缓存。include
属性能够绑定一个数组,里面是须要路由组件的name
值,能够实现对该路由组件进行缓存,若是不须要对路由进行缓存,直接移除该项元素便可。java
实现上面的功能,采用vuex
进行全局的缓存数据保存,定义为cacheView
;已经打开的路由页面用toolBarData
进行保存。下图是代码是代码设计总体图:git
须要添加一个路由页面到cacheView
,须要有actions setCacheView
来commit
一个change Event
对state
数据进行更改,而后修改后的数据会自动派发到App.vue
中使用到该数据的位置(即keep-alive
处)。而添加标签页也是相似的流程,再也不描述。至于为何要把标签页和路由缓存页面分离成两个数组,主要是有两方面的考虑:github
name
值不能知足需求。store
代码实现以下所示,主要须要比较详细说明的是clearToolItem
,这个函数是清除标签页。涉及两个规则:vuex
import router from '../router'
export default {
state: {
toolBarData:[],// 保存标签button的数组
cacheView:[] // 保存须要缓存的数组
},
getters: {
getToolData(state){
return state.toolBarData;
},
getCacheView(state){
return state.cacheView;
}
},
mutations: {
setToolData(state, data) { // 添加标签按钮,若是当前路由已经打开,则再也不重复添加
const inToolbar = state.toolBarData.find(item => item.detail === data.detail)
!inToolbar && state.toolBarData.push({
...data
});
},
setCacheView(state,data){ // 与setToolData相似
if(state.cacheView.includes(data.componentName))
return;
state.cacheView.push(data.componentName);
},
clearToolItem(state,detail){
const index = state.toolBarData.findIndex(item => item.detail === detail);
const isActive = router.app.$route.path == state.toolBarData[index]["detail"];
const len = state.toolBarData.length - 1;
state.toolBarData.splice(index,1);
(index == len || isActive) && router.push({path:state.toolBarData[state.toolBarData.length - 1]["detail"]});
},
clearCacheView(state,viewName){
const index = state.cacheView.findIndex(item => item == viewName);
state.cacheView.splice(index,1);
}
},
actions: {
commitToolBar({commit},data) {
commit("setToolData",data);
commit("setCacheView",data);
},
clearToolBar({commit},data){
commit("clearToolItem",data.detail);
},
clearCache({commit},data){
commit("clearCacheView",data);
}
}
}
复制代码
在App.vue
入口文件,使用keep-alive
对匹配的路由组件进行缓存,监听当前路由变化,添加缓存路由和标签。api
<template>
<el-main style="position:relative;margin-top:45px;">
<!--渲染标签的地方-->
<ToolBar></ToolBar>
<div class="routeWrap">
<transition name="fade-transform">
<keep-alive :include="cachedViews">
<router-view></router-view>
</keep-alive>
</transition>
</div>
</el-main>
</template>
复制代码
这里使用了elementui
的el-tag
标签,el-tag
标签带有动画、关闭按钮、主题color等属性,close
函数是清除该标签和清除缓存路由(已访问过)。click
主要是当对该标签项点击操做,则切换到该路由页面。其中active
是该标签匹配到当前路由时候处于激活状态(颜色高亮),el-tag
的动画比较生硬,因此关闭了。数组
<template>
<div class="toolbar"> <el-tag class="toolItem" type="info" :disable-transitions="false" :closable="item.id != 0" effect="plain" v-for="(item,index) in getToolData" :key="index" :class="{active:$route.path == item.detail}" @click="redirect(item)" @close="closeToolItem(item)" > <span class="dot" v-if="$route.path == item.detail"></span> {{item.name}} </el-tag> </div> </template>
<script>
import { mapGetters } from "vuex";
export default {
methods: {
closeToolItem(item, index) {
this.$store.dispatch("clearToolBar", item);
this.$store.dispatch("clearCache", item.componentName);
},
redirect(item) {
this.$router.push({ path: item.detail });
}
},
computed: {
...mapGetters(["getToolData", "getCacheView"])
},
watch: {
// 监听路由变化自动dispatch一个action
$route() {
// 路由组件名称(自定义)
const componentName =this.$route.matched[0]["components"]["default"][ "name"];
// 路由组件path
const detail = this.$route.path;
// 当前路由须要显示到tab标签上名字,如“发布公告”
const name = this.$route.meta[0]["name"];
this.$store.dispatch("commitToolBar", { name, detail, componentName });
}
}
};
</script>
复制代码
activated
和deactivated
采用了keep-alive
缓存的路由组件,从新进入该路由,路由组件不会从新建立,因此也就不会触发组件的生命周期函数(好比说beforeCreate
、mounted
等)。因此在对该页面进行数据更新或者清除数据。vue
为咱们提供了activated
和deactivated
生命周期函数,当从新进入路由组件会触发activated
函数,离开则会触发deactivated
。浏览器
<template>
<div> A page</div>
</template>
<script>
export default {
data(){
return {
form :{
name:'',
password:''
}
}
},
activated(){
this.getList()
},
deactivated(){
Object.keys(this.form).map(key => {
this.form[key] = ''
})
}
}
</script>
复制代码
到如今已经完成了相似于window tab
标签,从代码组织和设计上,能够比较清除看清代码组织的原理。这个实现主要是模仿了vue-element-admin
这个开源项目。缓存