Vue3 使用项目内嵌iFrame

背景

什么时候我们需要使用Vue3内嵌iFrame呢?答案是当我们多个项目需要共享一个页面的时候,我们需要在当前的Vue3的项目中内嵌一个iFrame的页面。或我们需要在一个网站嵌入另外一个网站。我们现在就有这样的一个使用场景,我们左侧有一个导航栏,这个导航栏可以点击跳转到不同的页面,一部分页面是本地的组件,一部分的页面是iFrame的页面。

问题

在实现的过程中我们遇到了如下的问题:

  • 当外侧的参数传入的时候,我们需要对外部的参数进行监听,刷新内部的页面
  • 当点击的时候,我们要根据不同的链接,自动的去渲染到正确的页面
  • 当我们在iFrame的页面进行刷新的时候,我们还要停留在当前的页面

操作

搭建

我们需要在Wrapper的项目中,定义出一个iFrame的页面,我们在创建之前,在我们开始操作之前,我们一定是有一个这样的页面,写过Vue3的人都应该清楚router-view的作用,我们在这里就不再过多的描述。

父页面的项目.vue 复制代码
<a-layout-content>
   <router-view></router-view>
</a-layout-content>

我们的左侧导航栏一般都是和后端的返回的路由绑定的,我们现在可以知道,我们之前的后端返回的数据结构如下:

json 复制代码
{
  "code": 200,
  "msg": "操作成功",
  "data": [
    {
      "name": "Monitoring",
      "path": "/Monitoring",
      "hidden": false,
      "redirect": "noRedirect",
      "component": "Layout",
      "alwaysShow": true,
      "meta": {
        "title": "父级",
        "link": null
      },
      "children": [
        {
          "name": "Load",
          "path": "load",
          "hidden": false,
          "component": "monitoring/load/index",
          "meta": {
            "title": "子组件",
            "noCache": false,
            "link": null
          }
        },
        {
          "name": "IframeChart",
          "path": "iframeChart",
          "hidden": false,
          "component": "https://www.baidu.com/#/iframe",
          "meta": {
            "title": "子组件-iFrame",
            "noCache": false,
            "link": null
          }
        }
      ]
    }
  ]
}

在接入iFrame ,上面都是我们的准备工作,接下来我们开始接入iFrame,首先我们先创建一个页面,这个页面,我们只用来显示iFrame的内容。具体的内容如iframe.vue下:

js 复制代码
<template>
  <iframe :src="iframeSrc" width="100%" height="100%" frameborder=""no"" border=""0″"/>
</template>

<script setup>
import { useStore } from 'vuex';
const store = useStore();
const iframeSrc = ref('');

const token = localStorage.getItem('token');

onMounted(() => {
  iframeSrc.value = `${route.meta.link}?token=${token}&source=a`;
  token=${token}&source=saas`;
});
</script>

我们有一个加载组件的公共方法:

js 复制代码
export const loadView = (view) => {
  return () => import(`@/views/${view}.vue`);
};

当然在这之前,我们需要对我们的路由进行处理,具体的处理逻辑如下:

ps:其中loadView('iframe')加载的就是我们之前写的iframe.vue

js 复制代码
 if (route.component.includes('http')) {
        route.meta.link = route.component;
        route.meta.isIframe = true;
        route.component = loadView('iframe');
}

我们这样操作下来,就完成了当我们在iFrame的页面进行刷新的时候,页面没有停留在当前页面的问题。接下来我们需要解决的。接下来我们需要解决的就是通信的问题,我们的父组件需要给子项传入一些必要的信息,在我们之前的写法中,token我们直接放在了url中进行通信,当时当我们切换用户或是切换项目的时候,我们需要对页面进行刷新。我们一般是在iframe加载后,对子组件进行消息发送,我们一般使用postMessage。我们根据这个要求,对iframe.vue文件进行代码更新,更新后的结果如下:

js 复制代码
<template>
  <iframe :src="iframeSrc" width="100%" ref="iframePageRef" @load="onIframeLoad" height="100%" frameborder=""no"" border=""0″"></iframe>
</template>

<script setup>
import { useStore } from 'vuex';
import { useRoute } from 'vue-router';

const route = useRoute();
const store = useStore();
const iframePageRef = ref(null);
const iframeSrc = ref('');

const token = localStorage.getItem('token');

onMounted(() => {
  iframeSrc.value = `${route.meta.link}/#/energyChart?token=${token}&source=saas`;
});

const onIframeLoad = () => {
  iframePageRef.value.contentWindow.postMessage(
    {
      projectId: store.state.projectId,
    },
    '*',
  );
};
</script>

然后我们在子项目中进行接收,接收的内容,我们在App.js中进行监听

js 复制代码
window.addEventListener('message', function (event) {
  if (event.data && event.data.projectId) {
    sessionStorage.setItem('projectId', event.data.projectId);
    store.commit('SET_ProjectId', event.data.projectId);
  }
});

这样的话,我们在项目刚开始渲染的时候,就可以拿到最新的projectId了,然后我们在projectId改变的时候需要通知子项目,这个时候子项目需要监听store中的projectId,子项目的的监听方法如下:

js 复制代码
watch(
  () => store.state.projectId,
  () => {
    queryData(); // 一些查询相关的操作
  },
);
相关推荐
Epat3 分钟前
关于一个小菜鸡是如何通过自定义 postcss 插件解决 color-mix 兼容问题的
前端
小小小小宇4 分钟前
webComponent实现一个拖拽组件
前端
满怀10154 分钟前
【Python核心库实战指南】从数据处理到Web开发
开发语言·前端·python
PBitW12 分钟前
工作中突然发现零宽字符串的作用了!
前端·javascript·vue.js
VeryCool13 分钟前
React Native新架构升级实战【从 0.62 到 0.72】
前端·javascript·架构
小小小小宇15 分钟前
JS匹配两数组中全相等对象
前端
xixixin_17 分钟前
【uniapp】uni.setClipboardData 方法失效 bug 解决方案
java·前端·uni-app
狂炫一碗大米饭18 分钟前
大厂一面,刨析题型,把握趋势🔭💯
前端·javascript·面试
星空寻流年24 分钟前
css3新特性第五章(web字体)
前端·css·css3
加油乐30 分钟前
JS计算两个地理坐标点之间的距离(支持米与公里/千米)
前端·javascript