无界微前端应用初探

✨背景

在新老平台过渡期间,两个平台的用户要分别在不同的平台办理业务或者查看数据,而且还要在两个平台之前来回登录,给用户造成一定的困扰。不仅如此在技术升级中,为了做到系统平滑流畅的升级,也是需要一种方案在不破坏目前架构和用户体验的基础上,完成这一系列操作。这个时候大家肯定是最先想到通过iframe嵌入的方式把两个平台融合在一起,但是这样的方式有些弊端。那如何做到丝滑、无感知的嵌入呢,下面就一起来探讨一下最近实践。

✨技术选型

iframeqiankun无界
优点1. 使用简单
2. 可以做到应用直接完全隔离
由于这玩意我也没研究过。以下是网上的总结:
1. 监听路由自动的加载、卸载当前路由对应的子应用
2. 完备的沙箱方案
3. 路由保持,浏览器刷新、前进、后退,都可以作用到子应用应用间通信简单,全局注入
1. 通过组件方式来使用为前端,主应用只需引入组件即可
2. 可以完美的做到应用隔离
3. 可以做到路由、状态的保活
4. 子应用的适配性极高,几乎不需任何多余配置
5. 通讯机制完善,提供多种通讯方式,直接上手可用
缺点1. 无法做到保持子应用状态
2. 完全隔离,使得子应用和主应用之间有割裂感
3. 通讯需要自己封装使用
1. 基于路由匹配,无法同时激活多个子应用,也不支持子应用保活
2. 改造成本较大
3. css 沙箱无法绝对的隔离,js 沙箱在某些场景下执行性能下降严重
4. 无法支持 vite 等 ESM 脚本运行
1. 子应用初始化加载时控制台会抛出错误
2. 站点需要跨域支持
3. 有些css定位还是会出现移位的情况

通过以上优缺点分析比较,故选定使用成本最低的无界方案来进行处理

✨通讯方式

props方式

主应用可以通过组件上的props属性给子应用传递数据和方法

<WujieVue name="xxx" url="http://xxx.xxx.xxx" :props="{data:'data',method:{method}}">

子应用通过window.$wujie.props来接受

window.$wujie.props.data
  
window.$wujie.props.method()
widnow方式

设置变量

// 主应用
window.mainValue = 'mainValue'
// 子应用
window.subValue = 'subValue'

获取变量

// 主应用调用子应用
window.document.querySelector("iframe[name=xxx]").contentWindow.subValue
// 子应用调用主应用
window.parent.mainValue
eventBus式

主应用使用方式

// 如果使用wujie
import { bus } from "wujie";

// 如果使用wujie-vue
import WujieVue from "wujie-vue";
const { bus } = WujieVue;

// 如果使用wujie-react
import WujieReact from "wujie-react";
const { bus } = WujieReact;

// 主应用监听事件
bus.$on("事件名字", function (arg1, arg2, ...) {});
// 主应用发送事件
bus.$emit("事件名字", arg1, arg2, ...);
// 主应用取消事件监听
bus.$off("事件名字", function (arg1, arg2, ...) {});

子应用使用方式

// 子应用监听事件
window.$wujie?.bus.$on("事件名字", function (arg1, arg2, ...) {});
// 子应用发送事件
window.$wujie?.bus.$emit("事件名字", arg1, arg2, ...);
// 子应用取消事件监听
window.$wujie?.bus.$off("事件名字", function (arg1, arg2, ...) {});

✨平台改造项

主应用:

安装

# vue2 框架
npm i wujie-vue2 -S
# vue3 框架
npm i wujie-vue3 -S

main.js 引入

// vue2
import WujieVue from "wujie-vue2";
// vue3
import WujieVue from "wujie-vue3";

const { bus, setupApp, preloadApp, destroyApp } = WujieVue;

Vue.use(WujieVue);

使用

<WujieVue name="唯一id" url="子应用地址" ></WujieVue>
子应用:
  1. 如不使用单例模式或预加载则无需任何改造
  2. 生命周期改造,具体改造方式可以自行查看官方文档

子应用改造

✨注意事项

  • 由于嵌套后主应用和子应用的localstorage和cookie都是公用一套的,需要注意命名规范否则会发生覆盖问题
  • 子应用一定要支持跨域的

✨避坑提醒

一、 子应用设置单例后,第二次进入子应用页面,路由不重载

  • 解决方案:路由版本过高,目前使用3.4.9解决此问题

二、由于嵌入后dom结构会发生变化,会导致子应用有些css定位不准的问题

  • 解决方案:主应用或者子应用最外层元素设置position: relative

三、vite4的子应用单例后,会在切换子应用的时候发生样式丢失问题

  • 解决方案:使用plugins插件方案解决
<WujieVue name="xxx" url="http://xxx.xxx.xxx" :props="{data:'data',method:{method}}" :plugins="plugins">

 computed: {
    plugins() {
      return [
        {
          patchElementHook(element, iframeWindow) {
            if (element.nodeName === 'STYLE') {
              element.insertAdjacentElement = function (_position, ele) {
                iframeWindow.document.head.appendChild(ele);
              };
            }
          },
        },
      ];
    },
  },
 

<think>好的,我现在需要回答用户关于无界微前端路由传参的问题。首先,我需要回忆一下无界微前端的基本概念和路由传参的相关知识。无界微前端是一种前端架构方案,允许将不同的子应用集成到主应用中,实现独立开发和部署。路由传参是在不同子应用或主应用之间通过URL传递参数的一种方式。 接下来,我需要确定用户可能关心的几个方面:路由传参的基本方法、不同场景下的应用、参数的类型和限制,以及可能遇到的常见问题。例如,用户可能想知道如何通过URL参数传递数据,或者如何在主应用和子应用之间同步路由状态。 然后,我需要考虑无界微前端的路由机制。通常,主应用负责整体的路由管理,而子应用可能使用不同的框架(如Vue、React等),需要适配主应用的路由系统。传参可以通过URL的查询参数(query parameters)、路径参数(path parameters)或者通过状态管理库(如Vuex、Redux)进行。不过,URL传参是最直接的方式,因为它便于分享和书签。 我需要分步骤解释如何实现路由传参。首先是主应用如何设置路由参数,比如在跳转到子应用的路由时附加参数。例如,主应用的路由可能是`/sub-app?param1=value1`,子应用需要解析这个参数。其次是子应用如何接收和处理这些参数,可能需要使用路由库(如vue-router或react-router)来获取查询参数。 还要提到动态路由传参的情况,比如路径参数`/sub-app/:id`,这时候子应用需要根据不同的id渲染不同的内容。同时,需要注意浏览器历史记录的管理,避免参数丢失或路由冲突。 另外,安全性也是一个考虑点,比如对参数进行验证和转义,防止XSS攻击。还要讨论参数的持久化,比如使用localStorage或sessionStorage来存储参数,但这样可能会增加复杂度。 最后,可能需要给出一个具体的示例,比如主应用使用Vue Router,子应用使用React Router,展示如何配置路由和传递参数。同时,提醒用户在传参过程中可能遇到的常见问题,比如编码问题(使用encodeURIComponent处理特殊字符)、子应用路由配置不正确导致参数无法正确解析等。 总结来说,我需要组织内容结构清晰,先介绍基本概念,再分步骤讲解传参方法,结合实际示例,最后给出注意事项和常见问题解决方案。确保语言简洁明了,符合用户的理解水平。</think>无界微前端中的路由传参是实现主应用与子应用、子应用之间数据通信的重要手段,主要通过URL参数和路由状态两种方式实现。以下是具体实现方式和示例: --- ### 一、通过URL参数传参(显式传参) **原理**:通过路由路径或查询字符串传递参数,参数暴露在URL中,适合简单数据传递。 #### 1. 路径参数(动态路由) ```javascript // 主应用路由配置 { path: '/child/:id', // 定义动态参数 id name: 'ChildPage', component: ChildAppWrapper } ``` 子应用通过路由对象获取: ```javascript // 子应用Vue示例) const id = this.$route.params.id; // 子应用(React示例) const { id } = useParams(); // react-router v6 ``` #### 2. 查询参数(Query String) 主应用跳转时拼接参数: ```javascript // 主应用跳转逻辑 router.push('/child-app?name=John&age=25'); ``` 子应用解析参数: ```javascript // Vue应用 const name = this.$route.query.name; // React子应用 import { useSearchParams } from 'react-router-dom'; const [searchParams] = useSearchParams(); const name = searchParams.get('name'); ``` --- ### 二、通过路由状态传参(隐式传参) **原理**:通过路由跳转时的`state`传递复杂对象,参数不会暴露在URL中,适合敏感或大数据量传输。 #### 主应用传递参数 ```javascript // Vue应用 this.$router.push({ path: '/child', state: { userInfo: { name: 'John', role: 'admin' } } }); // React主应用 navigate('/child', { state: { userInfo: { name: 'John', role: 'admin' } } }); ``` #### 子应用接收参数 ```javascript // Vue应用(需在路由配置中启用props) const route = useRoute(); const userInfo = route.state?.userInfo; // React子应用 import { useLocation } from 'react-router-dom'; const location = useLocation(); const userInfo = location.state?.userInfo; ``` --- ### 三、跨应用通信进阶方案 当需要高频或实时通信时,建议结合其他方案: 1. **全局状态管理**:主应用与子应用共享Vuex/Pinia/Redux Store 2. **CustomEvent通信**:通过`window.dispatchEvent`和`window.addEventListener`实现事件驱动 3. **Props传递**:主应用通过`<wujie-vue>`组件props向子应用注入数据 --- ### 四、注意事项 1. **编码问题**:URL参数需使用`encodeURIComponent`处理特殊字符 2. **参数长度**:URL有长度限制(约2000字符),大数据建议用路由state 3. **安全防范**:对接收参数进行校验,避免XSS攻击 4. **路由同步**:主应用需监听子应用路由变化,保持路由状态一致 --- **完整示例**:主应用Vue3)向子应用(React18)传递参数 ```html <!-- 主应用跳转 --> <template> <button @click="gotoChild">进入子应用</button> </template> <script setup> import { useRouter } from 'vue-router'; const router = useRouter(); const gotoChild = () => { router.push({ path: '/child-app/123', query: { from: 'main' }, state: { secretKey: 'abc123' } }); }; </script> ``` ```javascript // React子应用获取参数 import { useParams, useSearchParams, useLocation } from 'react-router-dom'; function ChildPage() { // 路径参数 const { id } = useParams(); // 123 // 查询参数 const [searchParams] = useSearchParams(); const from = searchParams.get('from'); // 'main' // 路由状态 const location = useLocation(); const secretKey = location.state?.secretKey; // 'abc123' return <div>{/* 渲染内容 */}</div>; } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值