Wellend 2024-04-30 10:55 采纳率: 75%
浏览 42
已结题

vue+element项目中多tag时,切换Tab时iframe套第三方html页面需要实现不刷新

vue+element项目中多tag时, iframe套第三方html页面,切换Tab时,iframe能不刷新吗?

img

appMain.vue

<!-- eslint-disable  -->
<template>
    <section class="app-main" :style="!isMobile ? 'padding-top:0px' : 'padding-top:0px'">
        <transition name="fade-transform" mode="out-in">
            <keep-alive>
                <router-view :key="key" />
            </keep-alive>
        </transition>
    </section>
</template>

<script>
/* eslint-disable */
export default {
    name: 'AppMain',
    computed: {
        isMobile() {
            const userAgent = navigator.userAgent.toLowerCase();
            const mobileKeywords = ['mobile', 'android', 'iphone', 'ipad', 'ipod'];

            for (let i = 0; i < mobileKeywords.length; i++) {
                if (userAgent.indexOf(mobileKeywords[i]) !== -1) {
                    return true;
                }
            }

            return false;
        },
        cachedViews() {
            return this.$store.state.tagsView.visitedViews;
        },
        key() {
            return this.$route.fullPath;
        }
    },
    mounted() {
        // 关闭标签触发
        this.$bus.$on('removeCache', (name, view) => {
            this.removeCache(name, view);
        });
    },
    methods: {
        // 获取有keep-alive子节点的Vnode
        getVnode() {
            // 判断子集非空
            if (this.$children.length == 0) return false;
            let vnode;
            for (let item of this.$children) {
                // 如果data中有key则代表找到了keep-alive下面的子集,这个key就是router-view上的key
                if (item.$vnode.data.key) {
                    vnode = item.$vnode;
                    break;
                }
            }
            return vnode ? vnode : false;
        },
        // 移除keep-alive缓存
        removeCache(name, view = {}) {
            let vnode = this.getVnode();
            if (!vnode) return false;
            let componentInstance = vnode.parent.componentInstance;
            // 这个key是用来获取前缀用来后面正则匹配用的
            let keyStart = vnode.key.split('/')[0];
            let thisKey = `${keyStart}${view.fullPath}`;
            let regKey = `${keyStart}${view.path}`;

            this[name]({ componentInstance, thisKey, regKey });
        },
        // 移除其他
        closeOthersTags({ componentInstance, thisKey }) {
            Object.keys(componentInstance.cache).forEach((key, index) => {
                if (key != thisKey) {
                    // 1 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断)
                    if (componentInstance.cache[key]) {
                        componentInstance.cache[key].componentInstance.$destroy();
                    }
                    // 2 删除缓存
                    delete componentInstance.cache[key];
                    // 3 移除key中对应的key
                    componentInstance.keys.splice(index, 1);
                }
            });
        },
        // 移除所有缓存
        closeAllTags({ componentInstance }) {
            // 1 销毁实例
            Object.keys(componentInstance.cache).forEach(key => {
                if (componentInstance.cache[key]) {
                    componentInstance.cache[key].componentInstance.$destroy();
                }
            });
            // 2 删除缓存
            componentInstance.cache = {};
            // 3 移除key中对应的key
            componentInstance.keys = [];
        },
        // 移除单个缓存
        closeSelectedTag({ componentInstance, regKey }) {
            let reg = new RegExp(`^${regKey}`);
            Object.keys(componentInstance.cache).forEach((key, i) => {
                if (reg.test(key)) {
                    // 1 销毁实例
                    if (componentInstance.cache[key]) {
                        componentInstance.cache[key].componentInstance.$destroy();
                    }
                    // 2 删除缓存
                    delete componentInstance.cache[key];
                    // 3 移除key中对应的key
                    componentInstance.keys.splice(i, 1);
                }
            });
        }
    }
};
</script>


嵌入页面文件代码

<!-- eslint-disable -->
<template>
  <div class="checkManage">
    <iframe
    style="width:100%;"
      :src="src"
      scrolling="no"
      :style="{ height: boxHeight + 'px' }"
      frameborder="0"
    />
  </div>
</template>

<script>
/* eslint-disable */
import conf from '@/config/auditManagement'
export default {
  name: "checkManage",
  data() {
    return {
      src: '',
      projectId: '',
      projectAbbreviation: '',
      // 初始化盒子高度
      boxHeight: 400,
    }
  },
  mounted() {
    // 当组件挂载完成后,设置盒子高度
    this.setBoxHeight();
    // 添加窗口大小改变的监听事件
    window.addEventListener('resize', this.setBoxHeight);
  },
  beforeDestroy() {
    // 组件销毁前移除监听事件
    window.removeEventListener('resize', this.setBoxHeight);
  },
  methods: {
    setBoxHeight() {
      // 设置盒子高度为浏览器视窗高度减去一个固定值(例如:200px)
      this.boxHeight = window.innerHeight - 50;
    },
    srcUrl (){
      this.src = conf.serverUrl + `/cims-ui/auditSystemback/index.html#projectManage?projectId=` + this.$route.query.projectId
      // this.src = `localhost:8081/#/projectManage?projectId=` + this.$route.query.projectId
      
      console.log(this.src, 'src') 
    }
  },
  created() {
    console.log(this.$route, '-------')
    this.srcUrl()
  },
};
</script>

<style lang="scss" scoped>


</style>


  • 写回答

22条回答 默认 最新

  • 专家-皆知 2024-04-30 10:55
    关注
    获得0.15元问题酬金

    参考免费微信小程序:皆我百晓生 作答,经由专家-皆知整理回复,如问题解决,望采纳;如仍有疑问,请评论回复。

    为了在 Vue+Element 项目中实现切换 Tab 时 iframe 套用的第三方 HTML 页面不刷新,你需要确保在 Vue 的路由切换机制中维持 iframe 的状态。从你提供的代码片段来看,AppMain 组件使用了 <keep-alive> 来缓存路由组件,这是一个好的开始。不过,对于嵌入的 iframe,我们需要采取额外的措施来防止其在标签页切换时重新加载。

    解决方案概述

    1. 利用 Vue 的事件系统:当标签页切换时,发送一个自定义事件来通知包含 iframe 的组件不要重新设置 iframe 的 src
    2. 在 iframe 组件中监听事件并控制加载逻辑:在 iframe 组件内,监听这个事件,仅在首次加载或特定条件下重新设置 src

    具体步骤

    修改 AppMain.vue

    AppMain.vue 中,当标签页切换时,触发一个全局事件,通知 iframe 组件无需重新加载。

    // 在 AppMain.vue 的 mounted 钩子或其他合适的地方添加
    mounted() {
        // ...现有逻辑
        this.$bus.$on('routeChanged', () => {
            this.$bus.$emit('iframeRefreshControl', false); // 发送事件,指示不需要刷新iframe
        });
    }
    

    修改嵌入页面组件 (假设为 CheckManage.vue)

    CheckManage.vue 中,监听这个全局事件,并据此决定是否更新 iframe 的 src

    // 在 CheckManage.vue 的 mounted 和 beforeDestroy 钩子中添加事件监听和移除
    mounted() {
        this.$bus.$on('iframeRefreshControl', (shouldRefresh) => {
            if (shouldRefresh && !this.hasLoadedOnce) {
                this.srcUrl(); // 只有当应该刷新且尚未加载过时才调用
                this.hasLoadedOnce = true; // 标记已加载过
            }
        });
    
        // ...现有逻辑
        this.srcUrl();
        // 初始化标志位
        this.hasLoadedOnce = false;
    },
    beforeDestroy() {
        this.$bus.$off('iframeRefreshControl');
        // ...现有逻辑
    }
    

    同时,在 data 函数中添加 hasLoadedOnce 属性。

    data() {
        return {
            // ...现有属性
            hasLoadedOnce: false, // 新增属性,记录iframe是否至少加载过一次
        };
    },
    

    注意事项

    • 确保 $bus 已经被正确设置,通常是通过 Vue.prototype 或者 Vuex 来全局注册一个事件总线。
    • 这个方案假设你有一个全局的事件总线 ($bus),如果你没有设置,需要先设置它。通常可以在项目的 main.js 中添加如下代码:
    new Vue({
      // ...
      beforeCreate() {
        Vue.prototype.$bus = this; // 或者使用 Vuex store 作为事件总线
      },
      // ...
    });
    
    • 本解决方案依赖于全局事件总线来传递状态,这是一种常见的做法,但并非唯一方法。根据你的项目架构,也可以考虑使用 Vuex 状态管理或者 Vue 自带的组件间通信方式来优化这一逻辑。

    以上方案应该能帮助你在切换 Tab 时保持 iframe 页面的状态,避免不必要的刷新。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 5月8日
  • 创建了问题 4月30日

悬赏问题

  • ¥15 is not in the mmseg::model registry。报错,模型注册表找不到自定义模块。
  • ¥15 安装quartus II18.1时弹出此error,怎么解决?
  • ¥15 keil官网下载psn序列号在哪
  • ¥15 想用adb命令做一个通话软件,播放录音
  • ¥30 Pytorch深度学习服务器跑不通问题解决?
  • ¥15 部分客户订单定位有误的问题
  • ¥15 如何在maya程序中利用python编写领子和褶裥的模型的方法
  • ¥15 Bug traq 数据包 大概什么价
  • ¥15 在anaconda上pytorch和paddle paddle下载报错
  • ¥25 自动填写QQ腾讯文档收集表