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(); // 一些查询相关的操作
  },
);
相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端