使用的小诺框架 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的增删改查操作。