前言

本文介绍的是在做微前端 single-spa 项目过程中,遇到的 Vue 子应用和 React 子应用互相跳转路由时遇到的问题。

项目情况:single-spa 项目,基座用的是 React,目前是2个子应用一个 Vue 一个 React。路由方案是 Vue Router,React Router + history。

有交互场景是从 Vue 子应用跳转到 React 子应用,或者从 React 子应用跳转到 Vue 子应用,因此遇到了问题。

遇到的问题

结合项目诉求和遇到的问题,大家可以先思考一下有什么解决方案~

------------------------------分割线------------------------------

解决的方案

主要是要处理好以下2个因素:

  • 正常触发当前页面的路由钩子
  • 正常传路由参数到目的页面

    我一开始尝试去查阅社区文章和看部分源码,看是否有什么特殊方式自主去触发路由钩子,等钩子处理完成之后再跳转去目的页面(跳去 Vue 用 Vue Router,跳去 React 用 React Router)

但看源码下来发现,想要触发 Prompt 还是需要调用 history.push 触发流程,想要触发 Vue Router 导航守卫还是需要调用 VueRouter.push 触发流程

所以结合这两点我整出了解决方案,已使用在项目当中,下面是封装的全局路由跳转工具:

window.micro = {
// 子应用,会在相应应用挂载完成后设置
apps: { vue: null, react: null },
history: {
push: (location, onComplete, onAbort) => {
const url = typeof location === 'string' ? location : location.path;
// 判断是哪个子应用
const currentIsReact = isReactApp();
const nextIsReact = isReactApp(`#${url}`);
// 处理路由参数
let state = {};
let query = {};
let name = '';
if (typeof location !== 'string') {
state = location.params || {};
query = location.query || {};
name = location.name || '';
}
if (!currentIsReact && nextIsReact) {
// vue 跳 react:先用 vue-router 跳,在跳完的回调里再用 history 跳
const reactHistoryHandle = () => {
onComplete?.();
history.push(`#/temp?t=${Math.random()}`);
history.replace({ state, pathname: url, search: setQueryStringArgs(query) });
// 因为跳多了1次 vue-router,所以 back 一下
window.micro.apps.vue2.$router.back();
};
window.micro.apps.vue.$router.push(name ? { name, params: state, query } : { path: url, query }, reactHistoryHandle, onAbort);
} else if (currentIsReact && !nextIsReact) {
// react 跳 vue:先用 history 跳临时路由,再用 vue-router 跳,要配合 history.listen 做处理
react2vue = () => {
window.micro.apps.vue.$router.push(name ? { name, params: state, query } : { path: url, query }, onComplete, onAbort);
};
history.push('/temp_react_to_vue');
} else if (currentIsReact && nextIsReact) {
// react 跳 react:没有特殊,正常用 history 跳
} else {
// vue 跳 vue:没有特殊,正常用 vue-router 跳
}
},
},
};

配合的监听和工具函数:

// 处理 react 跳 vue的情况

let react2vue = null;
history.listen((location, action) => {
// 处理在临时路由的下一个路由,要返回上一个路由时,需要跳过临时路由
if (location.pathname === '/temp_react_to_vue' && action === 'POP') {
history.goBack();
} else if (location.pathname === '/temp_react_to_vue') {
// 在这里跳去真实的 vue-router 路由
react2vue?.();
react2vue = null;
}
}); // 工具函数
function isReactApp(hash = location.hash) {
// 实际根据自己微服务项目的子应用情况判断
return hash === '' || hash === '#/'
|| ['#/list', '#/read/', '#/compose', '#/login'].some(router => hash.startsWith(router))
;
}
// 把query参数变成query字符串,如 {a:1, b:2} 返回 ?a=1&b=2
function setQueryStringArgs(args) {
let str = '';
args = args || {};
for (const [key, value] of Object.entries(args)) {
str += `${key}=${encodeURIComponent(String(value))}`;
}
return str ? `?${str}` : '';
}

总结

这是我在实际项目中使用的方案,如有更优雅更好的方案,希望在评论区和我讨论~

收获 / 小彩蛋

因为之前已经对 Vue Router 原理和源码比较熟悉了,所以这次借着这个问题,主要是去了解了 React Router 的 Prompt 组件的实现,这里简单总结一下:

「实践篇」解决微前端 single-spa 项目中 Vue 和 React 路由跳转问题的更多相关文章

  1. 解决vue单页路由跳转后scrollTop的问题

    作为vue的初级使用者,在开发过程中遇到的坑太多了.在看页面的时候发现了页面滚动的问题,当一个页面滚动了,点击页面上的路由调到下一个页面时,跳转后的页面也是滚动的,滚动条并不是在页面的顶部 在我们写路 ...

  2. SPA项目中,404页面 和 登陆页面 对应的路由,应该怎样控制?

    SPA项目中,404页面 和 登陆页面 对应的路由,应该怎样控制? 可以这样做: 登陆之前,所有页面跳到 登陆页面:包括随便输入的路由地址. 登陆后,跳到相应页面:随便输入的.不存在的路由地址,才跳到 ...

  3. 响应式 Web 设计指南「实践篇」

    无论你是奔赴战场.跑马拉松,还是构建一个响应式的站点,准备工作都是关键. 创建一个响应式的站点意味着要考虑多样化的设备生态系统. 如果没有适当的准备,你将发现自己会因为缺少必要的部分而忙里忙外,并且站 ...

  4. 微前端(qiankun)主应用共享React组件

    前言 最近需要重构一个老项目,定的方案用微前端去改造.主应用是老的项目,微应用是新的项目,由于重构时间比较紧张,子应用还需要使用父应用的一些组件.过程中遇到一些问题,记录一下. 方案 我们知道qian ...

  5. 「SpringBoot」如何优雅地管理SpringBoot项目

    本文主要讲述一下如何优雅地管理SpringBoot项目. 背景 课堂上,当小明形如流水地回答完沐芳老师提出来的问题时,却被至今没有对象的胖虎无情嘲讽了? 沐芳老师:小明,你平时是如何启动.停止你的Sp ...

  6. 前端MVVM模式及其在Vue和React中的体现

    MVVM相关概念 Mvvm 前端数据流框架精讲 1) MVVM典型特点是有四个概念:Model.View.ViewModel.绑定器.MVVM可以是单向绑定也可以是双向绑定甚至是不绑定 2) 绑定器: ...

  7. Gulp 搭建前端非SPA 项目, 修改文件浏览器自动刷新

    起因:需要搭建一个自动打包处理 sass / js (es6),自动监听文件变化时浏览器自动刷新的开发环境 项目目录 project build -css -js *.html src -html - ...

  8. 解决在 WP8/ WP8.1 项目中 引用 C++ 组件时出现的 System.TypeLoadException 错误

    本文为个人博客备份文章,原文地址: http://validvoid.net/wp-cpp-typeloadexception/ 使用 Visual Studio 2013 update 4 在 WP ...

  9. 解决React路由跳转时出现的红色警告: Warning: Failed prop type: Invalid prop `component` of type `object` supplied to `Route`, expected `function`.

    一.报警如图: 二.查找路由版本 我使用路由版本是4.3.1的,然后我测试所有4.0+版本都会出现以上警告. 三.未解决前的代码 三.我又解读了一下报警告内容的大致意思:就是props需要通过函数返回 ...

随机推荐

  1. Vue-表单验证-全选-反选-删除-批量删除

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  2. PAM学习小结

    PAM 目录 PAM 功能: 回文树 Fail指针 Trans指针 构建PAM 应用 P5496[模板]回文自动机(PAM) P4287[SHOI2011]双倍回文 P4555[国家集训队]最长双回文 ...

  3. CF549G题解

    变菜了,一年前做这种题10min出结论,现在对着样例胡半天都没结果 首先考虑从判断无解入手. 定义两个位置 \((i,j)\),若 \(a[i]=a[j]+(j-i)\),则 \(i\) 和 \(j\ ...

  4. 痞子衡嵌入式:MCUBootUtility v3.5发布,支持串行NOR的ECC及双程序启动

    -- 痞子衡维护的 NXP-MCUBootUtility 工具距离上一个大版本(v3.4.0)发布过去半年了,这一次痞子衡为大家带来了版本升级 v3.5.0,这个版本主要有几个非常重要的更新需要跟大家 ...

  5. 官宣 .NET 7 Preview 2

    今天,我们很高兴发布 .NET 7 预览版 2..NET 7 的第二个预览版包括对 RegEx 源生成器的增强.将 NativeAOT 从实验状态转移到运行时的进展,以及对"dotnet n ...

  6. 程序设计基础·Java学习笔记·面向对象(下)

    Java程序设计基础之面向对象(下) (补充了上的一些遗漏的知识,同时加入了自己的笔记的ヾ(•ω•`)o) (至于为什么分P,啊大概是为了自己查笔记方便(?)应该是("` 3′") ...

  7. Linux移植总结--Linux中asm和arch的软链接

    @ 目录 问题 include <asm/aaa.h>实际用的是asm-arm/aaa.h include <asm/arch/memory.h>实际用的是include/as ...

  8. Flask 之 WebSocket

    http:是一个协议 规定:数据传输格式 -/r/n/r/n 一次的请求,一次的响应,断开了 短链接 无状态 服务器收到的请求,做出的响应给客户端 客户端主动向服务器发起请求 基于socket sen ...

  9. 洛谷 P2375 动物园

    题目详情 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法 ...

  10. jinja2.exceptions.TemplateNotFound 报错处理

    一.检查模板文件夹是否正确. 遇到这个问题,首先需要检查你的模板文件夹命名是否规范,Flask默认会在工程下寻找templates文件夹,这个是默认配置,不能写成template或者其他名字.当然,如 ...