微前端 qiankun 框架接入问题记录

背景:需要搭建一个平台,这个平台的主要功能是集成各个子系统,方面对系统之间的统一管理。在搭建这样一个平台时,前端考虑使用微前端架构方式实现,使用的框架是 qiankun,本文主要记录在 qiankun 框架使用过程中遇到的问题,及解决方法。

问题一:本地联调时报跨域问题及子应用无法 fetch 到,如下:

解决方法,修改主应用的配置,如下:

问题二:主应用可以连接到子应用,但在主应用中未显示子应用,如下:

解决方法,修改主应用的配置,如下:

主应用中未提供子应用需要挂载的 dom 元素

问题三:vue-router3 路由重复点击页面报错,如图:

解决方法,在 router 路由文件中修改 push replace 方法:

import Vue from 'vue';
import VueRouter from 'vue-router';
import HomeView from '../views/HomeView.vue';
import AboutView from '../views/AboutView.vue';
import MicroApp from '../components/MicroApp.vue';

Vue.use(VueRouter);

const { isNavigationFailure, NavigationFailureType } = VueRouter;
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch((failure) => {
    if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
      throw failure;
    }
  });
};

const originalReplace = VueRouter.prototype.replace;
VueRouter.prototype.replace = function replace(location) {
  return originalReplace.call(this, location).catch((failure) => {
    if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
      throw failure;
    }
  });
};

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView,
  },
  {
    path: '/about',
    name: 'about',
    component: AboutView,
  },
  {
    path: '/child-app1',
    component: MicroApp,
  },
];

const router = new VueRouter({
  mode: 'history',
  routes,
});

export default router;

问题四:主应用加载子应用之后,子应用内的路由跳转失败,如图:

解决方法,在路由文件中修改加载子应用的路由,并在修改主应用中的路由跳转方法,如图:

参考链接:导航故障 | Vue Router

qiankun 接入时的前期问题,大多是配置错误,主应用和子应用 name 对应不上,或者主应用未给子应用提供容器标签等,主要参考链接:

常见问题 - qiankun

简单总结:

1、主应用配置

主应用挂载组件:/component/Micro.vue

安装 qiankun

$ yarn add qiankun # 或者 npm i qiankun -S
document.subApps = [
  {
    name: 'childApp1',
    entry: '//localhost:8081/child-app1/',
    container: '#container-child-app1',
    activeRule: '/child-app1',
  },
];
<template>
  <div id="container-child-app1"></div>
</template>

<script>
import { loadMicroApp } from 'qiankun';
import actions from '../../actions.js';

export default {
  name: 'microApp',
  mixins: [actions],
  data() {
    return {
      microApp: null,
    };
  },
  mounted() {
    const getMicroInfo = this.getMicroInfo();
    this.microApp = loadMicroApp(getMicroInfo, { singular: true });
  },
  beforeDestroy() {
    this.microApp.unmount();
  },
  methods: {
    // 手动加载微应用
    getMicroInfo() {
      const appIdentifying = this.$route.path.split('/')[1];
      let data = {};
      const href = window.location.host;
      for (let i = 0; i < document.subApps.length; i++) {
        const element = document.subApps[i];
        if (element.activeRule.includes(appIdentifying)) {
          if (typeof element.entry !== 'string') {
            data = {
              ...element,
              entry: element.entry[href]
                ? element.entry[href]
                : Object.values(element.entry)[0],
            };
          } else {
            data = { ...element };
          }
          data.props = {
            token: {
              userInfo: {
                userName: '小明',
                userId: '123',
                date: new Date().toLocaleString(),
              },
            },
          };
          data.activeRule = [appIdentifying];
          break;
        }
      }
      console.log('data::', data);
      return data;
    },
  },
};
</script>

 组应用挂载子应用的路由修改:

import Vue from 'vue';
import VueRouter from 'vue-router';
import HomeView from '../views/HomeView.vue';
import AboutView from '../views/AboutView.vue';
import MicroApp from '../components/MicroApp.vue';

Vue.use(VueRouter);

const { isNavigationFailure, NavigationFailureType } = VueRouter;
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch((failure) => {
    if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
      throw failure;
    }
  });
};

const originalReplace = VueRouter.prototype.replace;
VueRouter.prototype.replace = function replace(location) {
  return originalReplace.call(this, location).catch((failure) => {
    if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
      throw failure;
    }
  });
};

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView,
  },
  {
    path: '/about',
    name: 'about',
    component: AboutView,
  },
  {
    // 子应用路由
    path: '/child-app1',
    component: MicroApp,
  },
];

const router = new VueRouter({
  mode: 'history',
  routes,
});

export default router;

App.vue 可以指定子应用容器位置:

<template>
  <div id="app">
    <container-main>
      <el-breadcrumb separator-class="el-icon-arrow-right">
        <el-breadcrumb-item>
          <el-button type="text" @click="handleJumpParentHome"
            >主应用 home</el-button
          >
        </el-breadcrumb-item>
        <el-breadcrumb-item>
          <el-button type="text" @click="handleJumpParentAbout"
            >主应用 about</el-button
          >
        </el-breadcrumb-item>
        <el-breadcrumb-item>
          <el-button type="text" @click="handleJumpChildApp1"
            >子应用 home</el-button
          >
        </el-breadcrumb-item>
      </el-breadcrumb>
      <!-- 可以不写,写了之后未指定了子应用挂载位置 -->
      <div id="container-child-app1"></div>
    </container-main>
    <router-view />
  </div>
</template>

<script>
import ContainerMain from './components/ContainerMain.vue';

export default {
  name: 'App',
  components: {
    ContainerMain,
  },
  data() {
    return {};
  },

  methods: {
    handleJumpParentHome() {
      this.$router.push({
        path: '/',
      });
    },

    handleJumpParentAbout() {
      this.$router.push({
        path: '/about',
      });
    },

    handleJumpChildApp1() {
      this.$router.push({
        path: '/child-app1',
      });
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>

2、子应用配置

main.js 中配置:

import Vue from 'vue';
import App from './App.vue';
import routes from './router';
import VueRouter from 'vue-router';
import store from './store';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false;
Vue.use(ElementUI);

if (window.__POWERED_BY_QIANKUN__) {
  /* eslint-disable @typescript-eslint/camelcase */
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

let router = null;
let instance = null;
function render(props = {}) {
  console.log('子应用 render props::', props, 'instance====', instance);
  // sessionStorage.setItem('userInfo', JSON.stringify(props.token.userInfo));
  const { container } = props;
  router = new VueRouter({
    base: window.__POWERED_BY_QIANKUN__ ? '/child-app1/' : '/',
    mode: 'history',
    routes
  });

  instance = new Vue({
    router,
    store,
    render: (h) => h(App)
  }).$mount(container ? container.querySelector('#app') : '#app');
}

// 独立运行时
/* eslint-disable */
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap() {
  console.log('子应用 bootstrap ===========================');
}

let initialState = null;
export async function mount(props) {
  console.log('子应用 mount props ===============', props);
  sessionStorage.setItem('userInfo', JSON.stringify(props.token.userInfo));
  props.onGlobalStateChange((state, prev) => {
    // state: 变更后的状态; prev 变更前的状态
    console.log('子应用获取共享数据 state::', state, 'prev::', prev);
    // 接收主应用中的共享数据 并将其设置为全局变量
    Vue.prototype.$initialState = state;
  });
  props.setGlobalState({
    initialState:
      '子应用中修改主应用中的全局变量,实现住应用子应用间数据的双向双向通信'
  });

  render(props);
}
export async function unmount() {
  console.log('子应用 unmount==========');
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
  router = null;
}

子应用中的打包配置修改:

const { defineConfig } = require('@vue/cli-service');

module.exports = defineConfig({
  transpileDependencies: true,
  publicPath: '/child-app1/',
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*'
    }
  },
  configureWebpack: {
    output: {
      /**
       {
          name: 'childApp1',
          entry: '//localhost:8081/child-app1/',
          container: '#container-child-app1',
          activeRule: '/child-app1',
        },

        library 与 主应用中的 name 保持一致
       **/
      library: `childApp1`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      chunkLoadingGlobal: `webpackJsonp_childApp1` // webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal
    }
  }
});

代码上传到了 github 上,后序会持续更新代码。

GitHub - 13523010484/qiankun-vue

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/551546.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

postman汉化

一、postman历史版本下载&#xff1a;Postman 10.24.16 Download for Windows / Old Versions / FileHorse.comhttps://www.filehorse.com/download-postman/old-versions/ 二、汉化包下载&#xff1a; Releases hlmd/Postman-cn GitHubPostman汉化中文版. Contribute to h…

弹性 MapReduce(EMR)

一.产品简介 1产品概述 E腾讯云 EMR 提供基于云服务器&#xff08;CVM&#xff09;和容器服务&#xff08;TKE&#xff09;两种部署运行方式&#xff1a; 2.Agent 的安装目录 Linux 安装目录是/usr/local/qcloud/stargate和/usr/local/qcloud/monitor CoreOs 安装目录是/va…

【Redis 神秘大陆】006 灾备方案

六、Redis 灾备方案 6.1 存储方案 6.1.1 基础对比 RDB持久化AOF持久化原理周期性fork子进程生成持久化文件每次写入记录命令日志文件类型二进制dump快照文件文本appendonly日志文件触发条件默认超过300s间隔且有1s内超过1kb数据变更永久性每秒fsync一次文件位置配置文件中指…

ECharts数据大屏展示效果

ECharts数据大屏展示效果 前言1、效果预览1.2、视频效果 2、使用框架3、如何处理屏幕自适应效果4、ECharts模块、dataV大屏插件 编写与布局5、往期回顾总结&#xff1a; 前言 数据大屏需整体效果好看&#xff0c;界面缩放自适应大小&#xff0c;全屏展示铺满整个屏幕并自适应&a…

Linux 指令之文件

1.开发背景 记录 linux 下对文件操作的指令 2.开发需求 记录常用的文件操作指令 3.开发环境 linux 操作系统&#xff0c;如果不支持需要查看是否存在对应的可执行文件 4.实现步骤 4.1 查找字符串 查找指定目录下包含指定的字符串 grep -rn "Timer frequency" .…

怎么在桌面上添加待办清单 好用的桌面待办清单工具

在这个信息爆炸的时代&#xff0c;我们每个人都像是身处信息的洪流中&#xff0c;稍有不慎就可能被淹没。我常常被各种琐事包围&#xff0c;需要完成的任务数不胜数&#xff0c;而大脑的内存似乎总是有限。有时&#xff0c;我甚至会忘记一些重要的事项&#xff0c;这让我感到非…

记录一个解决win11安装天融信VPN蓝屏解决方法

当我们安装完天融信VPN产品后&#xff0c;有时候会导致电脑蓝屏&#xff01;&#xff01;&#xff01;&#xff01; 解决&#xff1a;默认是这个目录&#xff1a;C:\Windows\SysWOW64\drivers 把TopsecPF.sys 名称 改成TopsecPF.sys1就ok了

谈谈微前端

相关问题 为什么要用微前端微前端的优缺点 回答关键点 独立开发 独立运行 独立部署 自治 微前端是一种架构理念&#xff0c;它将较大的前端应用拆分为若干个可以独立交付的前端应用。这样的好处是每个应用大小及复杂度相对可控。在合理拆分应用的前提下&#xff0c;微前端能…

构建有序链表,有序链表的归并,反转链表

本次将对于构建有序链表&#xff0c;有序链表的归并&#xff0c;反转链表&#xff0c;进行一一介绍和代码分享。 首先是一些链表中的基本的函数&#xff1a; Node* creatList() {Node* headNode (Node*)malloc(sizeof(Node));assert(headNode);headNode->next NULL;retu…

AJAX (异步的JavaScript 和 XML)

目录 1、什么是AJAX 2、作用 1&#xff09;与服务器通信 2&#xff09;异步交互&#xff08;更新局部页面&#xff09; 3、AJAX 的基本工作原理 4、应用举例 5、jQuery与AJAX 6、使用jQeury实现AJAX 1&#xff09;$.ajax()&#xff1a;发送异步请求 2&#xff09;$.g…

LeetCode-924. 尽量减少恶意软件的传播【深度优先搜索 广度优先搜索 并查集 图 哈希表】

LeetCode-924. 尽量减少恶意软件的传播【深度优先搜索 广度优先搜索 并查集 图 哈希表】 题目描述&#xff1a;解题思路一&#xff1a;解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给出了一个由 n 个节点组成的网络&#xff0c;用 n n 个邻接矩阵图…

Ubuntu:VSCode中编译运行C++代码

版本&#xff1a;Ubuntu22.04.1 LTS 目录 1 安装VSCode并汉化 2 检查Ubuntu是否已经安装了 GCC 3 在VScode中安装C/C扩展 4 在VSCode中进行C/C配置 1 安装VSCode并汉化 安装VSCode&#xff08;参考之前博客Ubuntu&#xff1a;安装VSCode_ubuntu vscode-CSDN博客&#xff…

面向未来的内容营销:Kompas.ai的趋势预测能力

在这个快速变化的数字时代&#xff0c;内容营销的成功很大程度上取决于能否准确预测并迅速响应未来的趋势。拥有前瞻性的内容策略能够让品牌在竞争中占据优势&#xff0c;与受众建立更深层次的联系。本文将深入探讨预测未来趋势在内容营销战略中的价值&#xff0c;分析Kompas.a…

【LeetCode刷题记录】54. 螺旋矩阵

54 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例 2&#xff1a; 输入&#xf…

基于springboot实现知识管理系统项目【项目源码+论文说明】

基于springboot实现知识管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个专门适应师生作业交流形式的网站。本文介绍了知识管理系统的开发全过程。通过分析企业对于知识管理系统的需求&#xff0c;创建了…

51单片机学习笔记16 小型直流电机和五线四相电机控制

51单片机学习笔记16 小型直流电机和五线四相电机控制 一、电机分类二、小型直流电机控制1. 简介2. 驱动芯片ULN2003D3. 代码实现dc_motor_utils.cmain.c 三、五线四相步进电机控制1. 步进电机工作原理2. 构造3. 极性区分4. 驱动方式5. 28BYJ-48步进电机&#xff08;1&#xff0…

nextjs渲染篇

1 服务器组件 默认情况下&#xff0c;Next.js 使用服务器组件。 1.1 服务器组件是如何呈现的&#xff1f; 在服务器上&#xff0c;Next.js 使用 React 的 API 来编排渲染。渲染工作被拆分为多个块&#xff1a;按单个路段和Suspense 每个区块分两个步骤呈现&#xff1a; Re…

linux 挂载云盘 NT只能挂载2T,使用parted挂载超过2T云盘

一、删除原来挂载好的云盘和分区 1、查看挂载号的云盘 fdisk -l 发现我们有5千多G但是只挂载了2T&#xff0c;心里非常的慌张&#xff01;十分的不爽&#xff01; 好&#xff0c;我们把它干掉&#xff0c;重新分区&#xff01; 2、解除挂载 umount /homeE 没保存跳转到&…

Oracle 11g完全卸载教程(Windows)

文章目录 一、停止Oracle服务二、卸载Oracle1、卸载Oracle产品2、删除注册表3、删除环境变量以及其余文件 一、停止Oracle服务 进入服务 找到服务中的Oracle服务并且停止 全部停止运行成功 二、卸载Oracle 1、卸载Oracle产品 点击开始菜单找到Oracle&#xff0c;然后点击…

cobaltstrike 流量隐藏

云函数 新建一个云函数&#xff0c;在代码位置进行修改 首先导入 yisiwei.zip 的云函数包 PYTHON # -*- coding: utf8 -*- import json, requests, base64def main_handler(event, context):C2 https://49.xx.xx.xx # 这里可以使用 HTTP、HTTPS~下角标~ path event[path]h…