GitBucket
4.6.0
Toggle navigation
Sign in
Files
Branches
1
Tags
Issues
Pull Requests
Labels
Milestones
Wiki
08335
/
hivui-platform-template
hivui平台项目模板
Browse code
@中文描述:优化加载状态
@升级登记:1 @同步后端:0 @同步数据库:0 @同步配置:0 @向下兼容:1
master
1 parent
34ccabd
commit
afca7e4c2cfde8c56b16b3d57331b5166984e4c4
ganyi
authored
2 days ago
Showing
1 changed file
project/hivuiMain/components/tabpanel/panel.vue
Ignore Space
Show notes
View
project/hivuiMain/components/tabpanel/panel.vue
<template> <div class="pl-tabs-panel" :title="title" :style="tabStyle"> <div class="pl-loading pl-loading-fixed" v-show="url && !loaded" ref="dom-loader"> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <iframe v-if="hasUrl" ref="iframe" :name="'iframe' + name" @load="handleIframeLoad"></iframe> <slot v-else></slot> </div> </template> <script> import { getUrlValue, setUrlValue } from "@main/utils"; import { getToken } from '@main/utils/auth' export default { name: 'PTabpanel', props: { close: [String, Number, Boolean], itemData: Object, title: { type: String, default: "" }, name: { type: [String, Number], default: "" }, url: { type: String, default: "" }, index: [String, Number] }, data() { return { scrollTop: 0, loaded: false, hasUrl: !!this.url } }, computed: { active() { return this.$parent.currentName === this.name }, tabStyle() { return { position: "absolute", width: "100%", height: "100%", top: this.active ? 0 : "-200%", left: 0, opacity: this.active ? 1 : 0, visibility: this.active ? "visible" : "hidden", }; } }, watch: { active(val) { const iframe = this.getIframe(); if (!iframe) return if (val) { // 面板激活,加载地址 + 恢复滚动位置 this.setIframeSrc(); this.$nextTick(() => { this.restoreScrollTop(); }) } else { // 面板隐藏,保存当前滚动位置 this.saveScrollTop(); } } }, updated() { this.$parent.$emit('tab-nav-update'); }, mounted() { if (this.active) { this.setIframeSrc(); } }, methods: { getIframe() { return this.$refs.iframe || null; }, // 保存iframe滚动位置(增加异常捕获,跨域页面防止报错) saveScrollTop() { try { const iframe = this.getIframe(); if (iframe && iframe.contentDocument) { this.scrollTop = iframe.contentDocument.documentElement.scrollTop || 0; } } catch (e) { // 跨域iframe无法访问内部dom,直接忽略 } }, // 恢复滚动位置 restoreScrollTop() { try { const iframe = this.getIframe(); if (iframe && iframe.contentDocument) { iframe.contentDocument.documentElement.scrollTop = this.scrollTop; } } catch (e) { } }, // 设置iframe地址核心方法 setIframeSrc() { const iframe = this.getIframe(); if (!this.hasUrl || !iframe) return; // 地址为空不需要刷新 if (this.url === 'about:blank') { this.loaded = true; return; } // ⭐关键:赋值src前强制开启loading this.loaded = false; if (iframe.src !== this.url) { iframe.setAttribute('src', this.url); } else { // src没有变化,不会触发load事件,手动关闭loading this.loaded = true; } }, // 刷新当前iframe reload() { const iframe = this.getIframe(); if (!iframe) return; this.loaded = false; try { const urlToken = getUrlValue(iframe.contentWindow.location.href, "access_token"); const nowToken = getToken(); // 原有false开关保留,按需开启 if (false && !window._global && urlToken && nowToken && urlToken !== nowToken) { iframe.contentWindow.location = setUrlValue(decodeURIComponent(iframe.contentWindow.location.href), "access_token", nowToken); } else { iframe.contentWindow.location.reload(); } } catch (e) { // 跨域页面reload捕获异常 this.loaded = true; } }, // iframe加载完成事件 handleIframeLoad(evt) { const iframe = this.getIframe(); if (!iframe) return; try { if (!this.title && iframe.contentWindow?.document.title) { this.$emit("update:title", iframe.contentWindow.document.title); } } catch (e) { } this.loaded = true; this.$emit('onIframeLoad', this, evt); }, } } </script>
<template> <div class="pl-tabs-panel" :title="title" :style="tabStyle"> <div class="pl-loading pl-loading-fixed" v-show="url && !loaded" ref="dom-loader"> <span></span> <span></span> <span></span> <span></span> <span></span> </div> <iframe v-if="hasUrl" @load="handleIframeLoad" :name="'iframe' + name" ref="iframe"></iframe> <slot v-if="!hasUrl"></slot> </div> </template> <script> import { getUrlValue, setUrlValue, getUrlSearch } from "@main/utils"; import { getToken } from '@main/utils/auth' export default { name: 'PTabpanel', props: { close: [String, Number, Boolean], itemData: Object, title: { type: String, default: "" }, name: { type: [String, Number], default: "" }, url: { type: [String], default: "" }, index: [String, Number] }, data() { return { scrollTop: 0, loaded: false, loadTimer: null } }, computed: { tabStyle() { return { position: "absolute", width: "100%", top: this.active ? 0 : "-200%", left: 0, opacity: this.active ? 1 : 0, visibility: this.active ? "visible" : "hidden", }; }, active() { return this.$parent.currentName === this.name; }, //hasUrl改为计算属性,动态监听url变化 hasUrl() { return !(this.url == null || this.url === ''); } }, watch: { active(val) { let ifm = this.$refs["iframe"]; if (val) { this.setIframeSrc(); if (ifm && ifm.contentDocument) { this.$nextTick(() => { //保持原有的滚动位置 ifm.contentDocument.documentElement.scrollTop = this.scrollTop; }); } } else { if (ifm && ifm.contentDocument) { //保持原有的滚动位置 this.scrollTop = ifm.contentDocument.documentElement.scrollTop; } } } }, updated() { this.$parent.$emit('tab-nav-update'); }, mounted() { if (this.active) { this.setIframeSrc(); } }, beforeDestroy() { this.clearLoadTimer(); }, methods: { clearLoadTimer() { if (this.loadTimer) { clearTimeout(this.loadTimer); this.loadTimer = null; } }, // 启动加载超时兜底 startLoadTimer() { this.clearLoadTimer(); this.loadTimer = setTimeout(() => { this.loaded = true; }, 12000); }, setIframeSrc() { let ifm = this.$refs['iframe']; if (!this.hasUrl || this.loaded == true) { if (ifm && ifm.contentDocument) { ifm.contentWindow.document.body.scrollTop = this.scrollTop; } return; } if (ifm && this.url.indexOf("about:blank") < 0) { this.loaded = false; this.startLoadTimer(); // 开始兜底计时 ifm.setAttribute('src', this.url); } else { this.loaded = true; } }, reload() { let ifm = this.$refs['iframe']; this.loaded = false; this.startLoadTimer(); // 刷新页面同样开启兜底 let urlToken = getUrlValue(ifm.contentWindow.location.href, "access_token"); let nowToken = getToken(); if (false && !window._global && urlToken && nowToken && (urlToken != nowToken)) {//正式环境 ifm.contentWindow.location = setUrlValue(decodeURIComponent(ifm.contentWindow.location.href), "access_token", nowToken); } ifm.contentWindow.location.reload(); }, handleIframeLoad(evt) { // 正常触发load,清除超时定时器 this.clearLoadTimer(); let ifm = this.$refs['iframe']; // 尝试获取页面标题,增加try-catch防止跨域报错 try { if (this.title == "" && ifm.contentWindow.document.title != "") { this.$emit("update:title", ifm.contentWindow.document.title); } } catch (e) { // 跨域无法读取标题,静默捕获异常 } // 简化判断,移除危险的contentWindow.body读取(跨域会报错阻断代码) if (ifm.src && ifm.src !== "about:blank") { this.loaded = true; } else { this.loaded = true; } // 绑定beforeunload增加异常捕获 try { if (ifm.contentDocument) { ifm.contentWindow.addEventListener('beforeunload', () => { //this.loaded=false;//右击刷新 时进行加载状态 }); } } catch (e) { } this.loaded && this.$emit('onIframeLoad', this, evt); }, } } </script>
Show line notes below