若依框架点击顶部tag切换时,永远都是刷新的。刷新问题两种情况:普通view切换时刷新及iFrame切换刷新
一、普通view切换时刷新
原因是view的name与在菜单填写的大小写不一致,按若依框架规则,路由地址必须写为 camel
驼峰命名形式,组件名称必须写为 pascal
首字母全大写的形式。
参考:若依 | 点击顶部 tag 标签不自动刷新 - shayloyuki - 博客园
二、iFrame切换刷新问题
原因是iframe无法通过keep-alive缓存内容节点,每次都需要重新渲染刷新,iframe中keep-alive机制失效原因:iframe页里的内容并不属于节点的信息,所以使用keep-alive依然会重新渲染iframe内的内容。而且iframe每一次渲染就相当于打开一个新的网页窗口,即使把节点保存下来,在渲染时iframe页还是刷新的。
参考:1.vue中keep-alive对引入iframe的页面无效,实现iframe页面缓存问题_vue iframe 缓存_ll7425的博客-CSDN博客
2.GitHub - jmx164491960/vue-iframe-demo: 在vue中实现iframe keep-alive
解决思路:
route-link点击切换时用route-view渲染呈现,若component为空时则不呈现,可以增加一个iframe组件在route-view旁边,同时监听路由,若是需要iframe呈现则显示,置空component,并给予iframe的src链接就完成呈现,再控制切换时用v-show控制显示当前路由即可。
改造若依步骤:
1.在获取路由时,判断iframe标识的置空component,打开文件src\store\modules\permission.js
2.改造route-view呈现iframe内容 (暂时没空分析,不懂的加好友提问吧,把代码贴上来)
修改文件src\layout\components\AppMain.vue
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<router-view :key="key" />
</keep-alive>
</transition>
<!-- iframe页 -->
<iframe v-for="item in componentsArr" :ref="item.name" :id="item.name" frameborder="no"
:style="'width: 100%; height:' +height" scrolling="auto" v-show="$router.currentRoute.path.endsWith(item.path)"/>
</section>
</template>
<script>
import Cookies from "js-cookie";
export default {
name: "AppMain",
data() {
return {
componentsArr: [],
height: document.documentElement.clientHeight - 94.5 + "px;",
};
},
created() {
// 设置iframe页的数组对象
const componentsArr = this.getComponentsArr();
this.componentsArr = componentsArr;
// 判断当前路由是否iframe页
setTimeout(() => {
this.isOpenIframePage();
}, 200);
},
mounted: function () {
setTimeout(() => {
this.loading = false;
}, 300);
const that = this;
window.onresize = function temp() {
that.height = document.documentElement.clientHeight - 94.5 + "px;";
};
},
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews;
},
key() {
return this.$route.path;
},
},
watch: {
$route() {
// 判断当前路由是否iframe页
this.isOpenIframePage();
},
},
methods: {
// 根据当前路由设置hasOpen
isOpenIframePage() {
debugger;
var path = this.$router.currentRoute.path.split("/").pop();
var iframe=this.$refs[path];
if(iframe)
{
iframe=iframe[0];
}
if (iframe&&!iframe.isbindsrc) {
this.code = this.$router.currentRoute.query.code;
let menuId = this.$router.currentRoute.meta.menuId;
let uuid = Cookies.get("uuid");
let menuCode = this.$router.currentRoute.meta.menuCode;
let link =
this.$router.currentRoute.meta.frameAddress ||
"/yizumiapi/yisee/tabs2";
if (link.indexOf("?") >= 0) {
link += "&";
} else {
link += "?";
}
let url =
link + "menuId=" + menuId + "&uuid=" + uuid + "&mcode=" + menuCode;
iframe.src = url;
iframe.isbindsrc="true"
}
},
// 遍历路由的所有页面,把含有iframeComponent标识的收集起来
getComponentsArr() {
const routers = this.$store.state.permission.iframeRoutes; //this.$router;
//const routers = router.options.routes;
var iframeMenus = [];
var genMenus = (routes) => {
routes.forEach((item, index) => {
if (item.meta && item.meta.frameAddress) {
var it = Object.assign(item);
delete it.children;
iframeMenus.push(it);
}
if (item.children) {
genMenus(item.children);
}
});
};
genMenus(routers);
return iframeMenus;
},
},
};
</script>
<style lang="scss" scoped>
.app-main {
/* 50= navbar 50 */
min-height: calc(100vh - 50px);
width: 100%;
position: relative;
overflow: hidden;
}
.fixed-header+.app-main {
padding-top: 50px;
}
.hasTagsView {
.app-main {
/* 84 = navbar + tags-view = 50 + 34 */
min-height: calc(100vh - 84px);
}
.fixed-header+.app-main {
padding-top: 84px;
}
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 17px;
}
}
</style>
src\store\modules\permission.js 代码
import auth from '@/plugins/auth'
import router, { constantRoutes, dynamicRoutes } from '@/router'
import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import ParentView from '@/components/ParentView'
import InnerLink from '@/layout/components/InnerLink'
const permission = {
state: {
routes: [],
addRoutes: [],
defaultRoutes: [],
topbarRouters: [],
sidebarRouters: [],
iframeRoutes: [],
},
mutations: {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
},
SET_DEFAULT_ROUTES: (state, routes) => {
state.defaultRoutes = constantRoutes.concat(routes)
},
SET_TOPBAR_ROUTES: (state, routes) => {
state.topbarRouters = routes
},
SET_SIDEBAR_ROUTERS: (state, routes) => {
state.sidebarRouters = routes
},
SET_IFRAME_ROUTERS: (state, routes) => {
state.iframeRoutes = routes
},
},
actions: {
// 生成路由
GenerateRoutes({ commit },appId) {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters(appId).then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
router.addRoutes(asyncRoutes);
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes)
commit('SET_TOPBAR_ROUTES', sidebarRoutes)
debugger;
commit('SET_IFRAME_ROUTERS', iframeRoutes)
resolve(rewriteRoutes)
})
})
}
}
}
var iframeRoutes=[];
// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
return asyncRouterMap.filter(route => {
if (type && route.children) {
route.children = filterChildren(route.children)
}
if (route.component) {
// Layout ParentView 组件特殊处理
if (route.component === 'Layout') {
route.component = Layout
} else if (route.component === 'ParentView') {
route.component = ParentView
} else if (route.component === 'InnerLink') {
route.component = InnerLink
} else {
if(route.meta&&route.meta.frameAddress)
{
route.component=undefined;
if(iframeRoutes.filter(c=>c.name==route.name).length==0)
{iframeRoutes.push(route)}
}
else{
route.component = loadView(route.component)
}
}
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type)
} else {
delete route['children']
delete route['redirect']
}
return true
})
}
function filterChildren(childrenMap, lastRouter = false) {
var children = []
childrenMap.forEach((el, index) => {
if (el.children && el.children.length) {
if (el.component === 'ParentView' && !lastRouter) {
el.children.forEach(c => {
c.path = el.path + '/' + c.path
if (c.children && c.children.length) {
children = children.concat(filterChildren(c.children, c))
return
}
children.push(c)
})
return
}
}
if (lastRouter) {
el.path = lastRouter.path + '/' + el.path
}
children = children.concat(el)
})
return children
}
// 动态路由遍历,验证是否具备权限
export function filterDynamicRoutes(routes) {
const res = []
routes.forEach(route => {
if (route.permissions) {
if (auth.hasPermiOr(route.permissions)) {
res.push(route)
}
} else if (route.roles) {
if (auth.hasRoleOr(route.roles)) {
res.push(route)
}
}
})
return res
}
export const loadView = (view) => {
if (process.env.NODE_ENV === 'development') {
return (resolve) => require([`@/views/${view}`], resolve)
} else {
// 使用 import 实现生产环境的路由懒加载
return () => import(`@/views/${view}`)
}
}
export default permission