当前位置:   article > 正文

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

小诺框架

使用的小诺框架 vue2 版本

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

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

问题:

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

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

解决方案:

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

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

  1. /**
  2. * 标记路由状态
  3. * @param item 路由信息
  4. */
  5. function markIframeTags(item) {
  6. if (item.component == 'Iframe') {
  7. item.meta['__isIframe'] = true
  8. }
  9. }
  10. /**
  11. * 数组转树形结构
  12. * @param list 源数组
  13. * @param tree 树
  14. * @param parentId 父ID
  15. */
  16. const listToTree = (list, tree, parentId) => {
  17. list.forEach(item => {
  18. // 判断是否为父级菜单
  19. // eslint-disable-next-line eqeqeq
  20. // TODO:
  21. markIframeTags(item)
  22. if (item.pid == parentId) {
  23. const child = {
  24. ...item,
  25. key: item.key || item.name,
  26. children: []
  27. }
  28. // 迭代 list, 找到当前菜单相符合的所有子菜单
  29. listToTree(list, child.children, item.id)
  30. // 删掉不存在 children 值的属性
  31. if (child.children.length <= 0) {
  32. delete child.children
  33. }
  34. // 加入到树中
  35. tree.push(child)
  36. }
  37. })
  38. }
  39. export const generator = (routerMap, parent) => {
  40. return routerMap.map(item => {
  41. // eslint-disable-next-line no-unused-vars
  42.     // TODO:
  43. const { title, show, hideChildren, hiddenHeaderContent, target, icon, link, __isIframe } = item.meta || {}
  44. const currentRouter = {
  45. // 如果路由设置了 path,则作为默认 path,否则 路由地址 动态拼接生成如 /dashboard/workplace
  46. path: item.path || `${parent && parent.path || ''}/${item.key}`,
  47. // 路由名称,建议唯一
  48. name: item.name || item.key || '',
  49. // 该路由对应页面的 组件 :方案1
  50. // component: constantRouterComponents[item.component || item.key],
  51. // 该路由对应页面的 组件 :方案2 (动态加载)
  52. component: (constantRouterComponents[item.component || item.key]) || (() => import(`@/views/${item.component}`)),
  53. // meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)
  54. meta: {
  55. title: title,
  56. icon: icon || undefined,
  57. // hiddenHeaderContent: hiddenHeaderContent,
  58. target: target,
  59. link: link,
  60.         // TODO:
  61. __isIframe
  62. }
  63. }
  64. // 是否设置了隐藏菜单
  65. if (show === false) {
  66. currentRouter.hidden = true
  67. }
  68. // 是否设置了隐藏子菜单
  69. if (hideChildren) {
  70. currentRouter.hideChildrenInMenu = true
  71. }
  72. // 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠
  73. if (!currentRouter.path.startsWith('http')) {
  74. currentRouter.path = currentRouter.path.replace('//', '/')
  75. }
  76. // 重定向
  77. item.redirect && (currentRouter.redirect = item.redirect)
  78. // 是否有子菜单,并递归处理
  79. if (item.children && item.children.length > 0) {
  80. // Recursion
  81. currentRouter.children = generator(item.children, currentRouter)
  82. }
  83. return currentRouter
  84. })
  85. }

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

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

  1. const app = {
  2. state: {
  3.     // TODO:
  4. multiTabList: []
  5. },
  6. mutations: {
  7. // TODO:
  8. SET_MULTITAB_LIST: (state, val) => {
  9. state.multiTabList = val
  10. },
  11. },
  12. }
  13. export default app

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

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

  1. <script>
  2. import events from './events'
  3. export default {
  4. name: 'MultiTab',
  5. watch: {
  6.     // TODO:
  7. pages(nv) {
  8. const list = nv.reduce((res, item) => {
  9. if (item.meta.__isIframe == true) {
  10. res.push(item.name)
  11. }
  12. return res
  13. }, [])
  14. this.$store.commit('SET_MULTITAB_LIST', list)
  15. }
  16. },
  17. }
  18. </script>

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

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

  1. <template>
  2. <div :style="!$route.meta.hiddenHeaderContent ? 'margin: -24px -24px 0px;' : null">
  3. <div class="content">
  4. <div class="page-header-index-wide" ref="pageViewMain">
  5. <slot>
  6. <!-- keep-alive TODO: -->
  7. <keep-alive v-if="multiTab">
  8. <router-view ref="content" v-if="!isIframe" />
  9. <template v-else> </template>
  10. </keep-alive>
  11. <router-view v-else ref="content" style="margin: -12px -14px 0;" />
  12. <!-- keep-alive TODO: end: -->
  13. </slot>
  14. </div>
  15. </div>
  16. </div>
  17. </template>
  18. <script>
  19. import { mapState, mapGetters } from 'vuex'
  20. // TODO:
  21. function compareIsIframe(route) {
  22. return route.meta.__isIframe == true
  23. }
  24. export default {
  25. name: 'PageView',
  26. data() {
  27. return {
  28. tabs: {},
  29. tabIframeList: []
  30. }
  31. },
  32. computed: {
  33. ...mapState({
  34. multiTab: state => state.app.multiTab,
  35. // TODO:
  36. multiTabList: state => state.app.multiTabList
  37. }),
  38. // TODO:
  39. ...mapGetters(['userInfo']),
  40. // TODO:
  41. isIframe(){
  42. return this.$route.meta.__isIframe
  43. }
  44. },
  45. mounted() {
  46. // TODO:
  47. this.handleIframe(this.$route)
  48. },
  49. watch: {
  50. $route(nv) {
  51. this.handleIframe(nv)
  52. },
  53. // TODO:
  54. multiTabList(tabNames) {
  55. // 只保留存在的
  56. this.compareDelIframes(tabNames)
  57. }
  58. },
  59. methods: {
  60. // TODO:
  61. compareDelIframes(tabNames) {
  62. // 看看创建过的iframe 是不是 在tabs里面 如果没有就删除
  63. let isDel = false
  64. for (let index in this.tabIframeList) {
  65. const currentName = this.tabIframeList[index]
  66. if (!tabNames.includes(currentName)) {
  67. const elm = document.querySelector('.' + currentName)
  68. if (elm) {
  69. elm.remove()
  70. isDel = true
  71. }
  72. }
  73. }
  74. if (!isDel) return
  75. const resList = []
  76. // 最后重置数组里面的数据 tabIframeList
  77. const elms = document.querySelectorAll('.__is_iframe')
  78. if (elms) {
  79. elms.forEach(item => {
  80. resList.push(item.id)
  81. })
  82. }
  83. this.tabIframeList = resList
  84. },
  85. // TODO:
  86. __initIframe($route) {
  87. // height={height} src={url} style="width:102.5%;overflow:hidden;" frameBorder="0"
  88. const link = $route.meta.link
  89. const iframe = document.createElement('iframe')
  90. iframe.height = Number(document.documentElement.clientHeight) - 120 + 'px'
  91. iframe.src = link
  92. iframe.frameBorder = '0'
  93. // init style
  94. console.log()
  95. const pageHeaderHeight = this.$refs.pageHeight.$el.clientHeight
  96. iframe.style.width = '102.5%'
  97. iframe.style.height = window.innerHeight - 170 + 'px'
  98. iframe.style.overflow = 'hidden'
  99. iframe.style.display = 'block'
  100. iframe.className = '__is_iframe ' + $route.name
  101. iframe.id = $route.name
  102. return iframe
  103. },
  104. // TODO:
  105. __initIframeDisplay(className, isShow) {
  106. if (className) {
  107. // 隐藏指定的
  108. const targetIframe = document.querySelector('.' + className)
  109. if (targetIframe) {
  110. targetIframe.style.display = isShow ? 'block' : 'none'
  111. }
  112. } else {
  113. const iframes = document.querySelectorAll('.__is_iframe')
  114. // 全部隐藏
  115. iframes &&
  116. iframes.forEach(item => {
  117. if (item && item.style.display != 'none') {
  118. item.style.display = 'none'
  119. }
  120. })
  121. }
  122. },
  123. // TODO:
  124. handleIframe($route) {
  125. const pageViewMain = this.$refs.pageViewMain
  126. this.__initIframeDisplay()
  127. // add
  128. if (compareIsIframe($route)) {
  129. const iframe = document.querySelector('.' + $route.name)
  130. if (iframe) {
  131. // 显示
  132. this.__initIframeDisplay($route.name, true)
  133. } else {
  134. // 创建
  135. const newIframe = this.__initIframe($route)
  136. pageViewMain.append(newIframe)
  137. this.tabIframeList.push($route.name)
  138. }
  139. }
  140. },
  141. }
  142. }
  143. </script>

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/524651
推荐阅读
  

闽ICP备14008679号