实现小诺框架(vue2)的iframe缓存。

使用的小诺框架 vue2 版本

https://gitee.com/xiaonuobase/snowy/tree/v1.7.0/

TODO: 是提示 要添加的内容在这里!

问题:

小诺框架 是iframe直接加载的,导致无法缓存。

使用iframe导入其他页面的时候。会出现无法缓存的问题。

解决方案:

需要缓存的iframe 不进行删除处理。

  • 在src\router\generator-routers.js添加函数。并替换listToTree函数的内容。替换generator函数

/**
 * 标记路由状态
 * @param item 路由信息
 */
function markIframeTags(item) {
  if (item.component == 'Iframe') {
    item.meta['__isIframe'] = true
  }
}

/**
 * 数组转树形结构
 * @param list 源数组
 * @param tree 树
 * @param parentId 父ID
 */
const listToTree = (list, tree, parentId) => {
  list.forEach(item => {
    // 判断是否为父级菜单
    // eslint-disable-next-line eqeqeq
    // TODO:
    markIframeTags(item)
    if (item.pid == parentId) {
      const child = {
        ...item,
        key: item.key || item.name,
        children: []
      }
      // 迭代 list, 找到当前菜单相符合的所有子菜单

      listToTree(list, child.children, item.id)
      // 删掉不存在 children 值的属性
      if (child.children.length <= 0) {
        delete child.children
      }
      // 加入到树中
      tree.push(child)
    }
  })
}
export const generator = (routerMap, parent) => {
  return routerMap.map(item => {
    // eslint-disable-next-line no-unused-vars
    // TODO:
    const { title, show, hideChildren, hiddenHeaderContent, target, icon, link, __isIframe } = item.meta || {}
    const currentRouter = {
      // 如果路由设置了 path,则作为默认 path,否则 路由地址 动态拼接生成如 /dashboard/workplace
      path: item.path || `${parent && parent.path || ''}/${item.key}`,
      // 路由名称,建议唯一
      name: item.name || item.key || '',
      // 该路由对应页面的 组件 :方案1
      // component: constantRouterComponents[item.component || item.key],
      // 该路由对应页面的 组件 :方案2 (动态加载)
      component: (constantRouterComponents[item.component || item.key]) || (() => import(`@/views/${item.component}`)),
      // meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)
      meta: {
        title: title,
        icon: icon || undefined,
        // hiddenHeaderContent: hiddenHeaderContent,
        target: target,
        link: link,
        // TODO:
        __isIframe
      }
    }
    // 是否设置了隐藏菜单
    if (show === false) {
      currentRouter.hidden = true
    }
    // 是否设置了隐藏子菜单
    if (hideChildren) {
      currentRouter.hideChildrenInMenu = true
    }
    // 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠
    if (!currentRouter.path.startsWith('http')) {
      currentRouter.path = currentRouter.path.replace('//', '/')
    }
    // 重定向
    item.redirect && (currentRouter.redirect = item.redirect)
    // 是否有子菜单,并递归处理
    if (item.children && item.children.length > 0) {
      // Recursion
      currentRouter.children = generator(item.children, currentRouter)
    }
    return currentRouter
  })
}

上方操作主要是进行标记是否是iframe类型组件。

  • 在src\store\modules\app.js 在state添加状态和在mutations添加方案(!!!不是替换

const app = {
  state: {
    // TODO:
    multiTabList: []
  },
  mutations: {
    // TODO:
    SET_MULTITAB_LIST: (state, val) => {
      state.multiTabList = val
    },
  },
}

export default app

在vuex 中添加一个状态记录标签栏所有的iframe状态的路由。

  • src/components/MultiTab/MultiTab.vue watch监听pages

<script>
import events from './events'

export default {
  name: 'MultiTab',
  watch: {
    // TODO:
    pages(nv) {
      const list = nv.reduce((res, item) => {
        if (item.meta.__isIframe == true) {
          res.push(item.name)
        }
        return res
      }, [])
      this.$store.commit('SET_MULTITAB_LIST', list)
    }
  },
}
</script>

主要就是监听pages属性发生改变。然后将所有是iframe的放到vuex中的multiTabList里面。

  • 在src\layouts\PageView.vue替换内容

<template>
  <div :style="!$route.meta.hiddenHeaderContent ? 'margin: -24px -24px 0px;' : null">
    
    <div class="content">
      <div class="page-header-index-wide" ref="pageViewMain">
        <slot>
          <!-- keep-alive TODO: -->
          <keep-alive v-if="multiTab">
            <router-view ref="content" v-if="!isIframe" />
            <template v-else> </template>
          </keep-alive>
          <router-view v-else ref="content" style="margin: -12px -14px 0;" />
          <!-- keep-alive TODO: end: -->
        </slot>
      </div>
    </div>
  </div>
</template>

<script>
import { mapState, mapGetters } from 'vuex'
// TODO:
function compareIsIframe(route) {
  return route.meta.__isIframe == true
}
export default {
  name: 'PageView',
  data() {
    return {
      tabs: {},
      tabIframeList: []
    }
  },
  computed: {
    ...mapState({
      multiTab: state => state.app.multiTab,
      // TODO:
      multiTabList: state => state.app.multiTabList
    }),
    // TODO:
    ...mapGetters(['userInfo']),
    // TODO:
    isIframe(){
      return this.$route.meta.__isIframe
    }
  },
  mounted() {
    // TODO:
    this.handleIframe(this.$route)
  },
  watch: {
    $route(nv) {
      this.handleIframe(nv)
    },
    // TODO:
    multiTabList(tabNames) {
      // 只保留存在的
      this.compareDelIframes(tabNames)
    }
  },
  methods: {
    // TODO:
    compareDelIframes(tabNames) {
      // 看看创建过的iframe 是不是 在tabs里面 如果没有就删除
      let isDel = false
      for (let index in this.tabIframeList) {
        const currentName = this.tabIframeList[index]
        if (!tabNames.includes(currentName)) {
          const elm = document.querySelector('.' + currentName)
          if (elm) {
            elm.remove()
            isDel = true
          }
        }
      }
      if (!isDel) return
      const resList = []
      // 最后重置数组里面的数据 tabIframeList
      const elms = document.querySelectorAll('.__is_iframe')
      if (elms) {
        elms.forEach(item => {
          resList.push(item.id)
        })
      }
      this.tabIframeList = resList
    },
    // TODO:
    __initIframe($route) {
      // height={height} src={url} style="width:102.5%;overflow:hidden;" frameBorder="0"
      const link = $route.meta.link
      const iframe = document.createElement('iframe')
      iframe.height = Number(document.documentElement.clientHeight) - 120 + 'px'
      iframe.src = link
      iframe.frameBorder = '0'
      // init style
      console.log()
      const pageHeaderHeight = this.$refs.pageHeight.$el.clientHeight
      iframe.style.width = '102.5%'
      iframe.style.height = window.innerHeight - 170 + 'px'
      iframe.style.overflow = 'hidden'
      iframe.style.display = 'block'
      iframe.className = '__is_iframe ' + $route.name
      iframe.id = $route.name

      return iframe
    },
    // TODO:
    __initIframeDisplay(className, isShow) {
      if (className) {
        // 隐藏指定的
        const targetIframe = document.querySelector('.' + className)
        if (targetIframe) {
          targetIframe.style.display = isShow ? 'block' : 'none'
        }
      } else {
        const iframes = document.querySelectorAll('.__is_iframe')
        // 全部隐藏
        iframes &&
          iframes.forEach(item => {
            if (item && item.style.display != 'none') {
              item.style.display = 'none'
            }
          })
      }
    },
    // TODO:
    handleIframe($route) {
      const pageViewMain = this.$refs.pageViewMain
      this.__initIframeDisplay()
      // add
      if (compareIsIframe($route)) {
        const iframe = document.querySelector('.' + $route.name)
        if (iframe) {
          // 显示
          this.__initIframeDisplay($route.name, true)
        } else {
          // 创建
          const newIframe = this.__initIframe($route)
          pageViewMain.append(newIframe)
          this.tabIframeList.push($route.name)
        }
      }
    },
  }
}
</script>

主要进行的就是DOM的增删改查操作。

猜你喜欢

转载自blog.csdn.net/qq_44560147/article/details/129212223