vue 处理页面缓存问题,点击tab标签不刷新页面,点击菜单刷新页面,附带处理报表iframe缓存页面
效果图1、index页面 主要代码<keep-alive :include="keepAliveList"><router-view class="avue-view" v-if="keepAlive"/></keep-alive>provide() {return {index: this,routerRefresh: this.routerRefresh};
一、效果图
实现原理利用 keep-alive :include
当点击菜单,判断keepAliveList是否含有该菜单,如果没有,则把菜单页面name直接添加进keepAliveList,如果有,则删除,在进行添加
二、主要代码
1、index页面 主要代码
<keep-alive :include="keepAliveList">
<router-view class="avue-view" v-if="keepAlive"/>
</keep-alive>
provide() {
return {
index: this,
routerRefresh: this.routerRefresh
};
},
data() {
return {
keepAlive:true,
keepAliveList: [],
};
},
watch: {
"$store.state.common.keepAliveList": {
handler: function (val, oldVal) {
this.keepAliveList = val;
},
deep: true,
immediate: true,
},
},
routerRefresh() {
this.keepAlive = false;
this.$nextTick(() => {
this.keepAlive = true;
});
},
2、sidebarItem 页面 methods
//删除缓存
delKeepAliveList(name) {
if (this.$store.state.common.keepAliveList.includes(name)) {
this.$store.commit("delKeepAliveList",name);
}
},
//设置缓存
setKeepAliveList(name) {
this.$store.commit("setKeepAliveList",name);
},
open(item) {
this.routerRefresh();
let path = item.path;
let name = path.substring(path.lastIndexOf("/") + 1); //页面name
this.delKeepAliveList(name);
if (this.screen <= 1) this.$store.commit("SET_COLLAPSE");
if (this.validIsOpen(item)) {
window.open(item[this.pathKey]);
} else {
this.$nextTick(() => {
this.setKeepAliveList(name);
this.$router.$avueRouter.group = item.group;
this.$router.$avueRouter.meta = item.meta;
this.$router.push({
path: this.$router.$avueRouter.getPath(
{
name: item[this.labelKey],
src: item[this.pathKey],
},
item.meta
),
query: item.query,
});
});
}
},
3、store页面
state:{
keepAliveList:getStore({name: 'keepAliveList'})||[],
},
mutations:{
setKeepAliveList(state, name) {
state.keepAliveList.push(name);
setStore({ name: "keepAliveList", content: state.keepAliveList });
},
delKeepAliveList(state, name) {
state.keepAliveList = state.keepAliveList.filter(function(i) {
return i != name;
});
setStore({ name: "keepAliveList", content: state.keepAliveList });
},
}
三、封装mixins(升级)
升级原因:因为前面方法只针对点击菜单,点击其他按钮弹出页面无效,最开始想通过路由全局钩子完成,但是路由一直值不显示,而后改成了mixins方法,及在需要的地方引入即可
keepAlive.js 文件
export default {
inject: ["routerRefresh"],
data(){
return {
NokeepAlive:[]//配置不缓存的页面name
}
},
methods: {
//删除缓存
delKeepAliveList(name) {
if (this.isKeepAlive(name)) {
this.routerRefresh();
if (this.$store.state.common.keepAliveList.includes(name)) {
this.$store.commit("delKeepAliveList", name);
}
}
},
//设置缓存
setKeepAliveList(name) {
if (this.isKeepAlive(name)) {
this.$store.commit("setKeepAliveList", name);
}
},
//是否缓存
isKeepAlive(name) {
return this.NokeepAlive.includes(name) ? false : true;
}
}
};
使用
import keepAlive from "@/mixins/keepAlive";//1、引入文件:
mixins:[keepAlive], //2、加入mixins
//3、获取页面name
let path = item.path;
let name = path.substring(path.lastIndexOf("/") + 1);
//4、判断删除缓存
this.delKeepAliveList(name);
//5、设置缓存
this.$nextTick(() => {
this.setKeepAliveList(name);
}
四、处理iframe报表缓存
实现思路:动态注册报表组件,利用hasOpen 和 $route.path 控制报表是否显示,如果点击的是菜单,则hasOpen设置为false 然后再设置为true,如果点击的是tag标签,则不进行处理。如果刷新了页面,需要从缓存里面取iframe页面的hasOpen属性,否则,当切换页面标签时。hasOpen为false, 则不会显示iframe页面
1、判断哪些报表需要缓存
const exceptRoute = ["repconfiguration", "reportlist"];//二级目录
let reportKey = ["work"];//一级目录
//判断是否是有Iframe的报表页面
isHasReportKey(path) {
let flag = false;
reportKey.forEach((item) => {
if (path.indexOf(item) != -1) {
flag = true;
}
});
return flag;
},
isReportIframe(path) {//判断是否是有Iframe的报表页面
return this.isHasReportKey(path) &&
!exceptRoute.includes(path.substring(path.lastIndexOf("/") + 1))
? true
: false;
}
2、通过component组件处理报表组件
<keep-alive :include="keepAliveList">
<router-view class="avue-view" v-if="keepAlive && !isIframeComp" />
</keep-alive>
<component
class="avue-view rr iframe"
:is="item.name"
v-for="item in hasOpenComponentsArr"
:key="item.index"
:ref="item.name"
v-show="$route.path === item.path"
></component>
3、监听路由变化,判断是否是含有iframe的页面
//判断当前路由是否是报表
$route(val) {
if (this.isReportIframe(val.path)) {
this.isIframeComp = true;
} else {
this.isIframeComp = false;
}
},
4、监听菜单变化,注册报表组件
"$store.state.user.menu": {
handler: function (n) {
const componentsArr = this.getComponentsArr(n);
componentsArr.forEach((item) => {
Vue.component(item.name, item.comp);
});
this.myComponent = componentsArr;
},
},
5、动态组将iframe组件
//动态注册iframe组件
getComponentsArr(routes) {
let componentsArr = [];
if (this.$store.state.common.iframePage.length > 0) {
componentsArr = this.$store.state.common.iframePage;
}
let iframeArr = [];
routes.forEach((element) => {
let reportPath = element.path.split("/");
if (reportKey.includes(reportPath[1])) {
let iframeObj = {};
element.children.forEach((element1, index) => {
let name = element1.path.substring(
element1.path.lastIndexOf("/") + 1
);
if (!exceptRoute.includes(name)) {
let myc = (resolve) =>
require([`../../views${element1.path}.vue`], resolve);
iframeObj = {
name: name,
path: element1.path,
hasOpen: false,
comp: myc,
index: index,
};
iframeArr.push(iframeObj);
}
});
}
});
//从缓存里面取值,重新赋值hasOpen
componentsArr.forEach((store_item)=>{
iframeArr.forEach((item)=>{
if(item.name == store_item.name){
item.hasOpen = store_item.hasOpen
}
})
})
return iframeArr;
},
6、记录已经打开的报表组件
computed:
hasOpenComponentsArr() {
return this.myComponent.filter((item) => item.hasOpen);
},
7、处理报表是否显示
isOpenIframePage(clickType) {
const target = this.myComponent.find((item) => {
return item.path === clickType.split("-")[1];
});
if (this.validatenull(target)) return;
//如果点击的是tag,则设置为显示状态
if (clickType.indexOf("menu") != "-1") {
target.hasOpen = false;
this.$nextTick(() => {
target.hasOpen = true;
this.$store.commit("getIframePage", this.myComponent);
});
}
},
8、处理存储数据(store.state)
//state
iframePage:getStore({name:"iframePage"})||[],
clickIframeMenuType:"menu"
//mutations
getClickIframeMenuType:(state,clickType) => {
state.clickIframeMenuType = clickType;
},
getIframePage:(state,iframePage)=>{
state.iframePage = iframePage;
setStore({ name: "iframePage", content: state.iframePage });
},
9、处理点击事件
//tag点击事件
if(this.isReportIframe(path)){
this.$store.commit("getClickIframeMenuType",`menu-${item.path}`);
}
//菜单点击事件
if(this.isReportIframe(item.name) ) {
this.$store.commit(
"getClickIframeMenuType",
`tag-${item.name}`
);
}
五、处理三级路由无法缓存的问题
解决思路:扁平化代码
更多推荐
所有评论(0)