若依框架点击顶部tag切换时,永远都是刷新的。刷新问题两种情况:普通view切换时刷新及iFrame切换刷新
一、普通view切换时刷新

原因是view的name与在菜单填写的大小写不一致,按若依框架规则,路由地址必须写为 camel 驼峰命名形式,组件名称必须写为 pascal首字母全大写的形式。

参考:若依 | 点击顶部 tag 标签不自动刷新 - shayloyuki - 博客园

若依框架前端切换TagView时刷新问题

若依框架前端切换TagView时刷新问题

二、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

若依框架前端切换TagView时刷新问题

 若依框架前端切换TagView时刷新问题

若依框架前端切换TagView时刷新问题

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

发表回复