Vite+微前端Qiankun-状态管理

news2025/3/20 11:26:12

一、前言

在微前端架构中,状态管理是一个重要的课题。由于子应用是独立的,它们之间可能需要共享状态或通信。以下是基于qiankun微前端架构的状态管理方案,结合Vue 3Vite的实现。

二、状态管理方案

在微前端中,状态管理可以分为以下几种方式:

1. 主应用和子应用共享状态

  • 通过全局状态管理库(如 PiniaVuex)在主应用中管理全局状态,子应用通过主应用提供的接口访问或修改状态。
  • 使用 qiankuninitGlobalState 方法实现主应用和子应用之间的状态共享。

2. 子应用独立状态管理

  • 每个子应用使用自己的状态管理库(如 PiniaVuex),状态独立管理,不与其他子应用共享。

3. 事件通信

  • 使用 CustomEventEventBus 实现子应用之间的通信。

三、使用 qiankuninitGlobalState 实现状态共享

qiankun提供了initGlobalState方法,用于在主应用和子应用之间共享状态。

1. 主应用配置

在主应用中初始化全局状态。

// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { registerMicroApps, start, initGlobalState } from 'qiankun';

const app = createApp(App);
app.use(router);
app.mount('#app');

// 初始化全局状态
const initialState = {
  user: {
    name: 'Main App User',
  },
};

const actions = initGlobalState(initialState);

// 监听状态变化
actions.onGlobalStateChange((state, prevState) => {
  console.log('主应用:状态变化', state, prevState);
});

// 注册子应用
registerMicroApps([
  {
    name: 'subApp1',
    entry: '//localhost:7101',
    container: '#subapp-container',
    activeRule: '/subApp1',
  },
  {
    name: 'subApp2',
    entry: '//localhost:7102',
    container: '#subapp-container',
    activeRule: '/subApp2',
  },
]);

// 启动 qiankun
start();

2. 子应用配置

在子应用中获取和修改全局状态。

// subApp1/src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

let instance = null;

function render(props = {}) {
  const { container } = props;
  instance = createApp(App);
  instance.use(router);
  instance.mount(container ? container.querySelector('#app') : '#app');

  // 获取全局状态
  if (props.onGlobalStateChange && props.setGlobalState) {
    props.onGlobalStateChange((state, prevState) => {
      console.log('子应用1:状态变化', state, prevState);
    });

    // 修改全局状态
    props.setGlobalState({
      user: {
        name: 'SubApp1 User',
      },
    });
  }

    // 将 props 注入到 Vue 实例中
    instance.provide('MAIN_APP_PROPS', props);
}

if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap() {
  console.log('subApp1 bootstrap');
}

export async function mount(props) {
  console.log('subApp1 mount');
  render(props);
}

export async function unmount() {
  console.log('subApp1 unmount');
  instance.unmount();
  instance = null;
}

3. Vue实例中修改全局变量

在配置中已经将主应用传过来的prop对象参数,使用依赖注入的方式注入到全局

instance.provide('MAIN_APP_PROPS', props);

vue实例中可以使用inject获取这个参数,从而使用prop参数里面带的onGlobalStateChange、setGlobalState两个函数管理全局状态

/**
* test.vue TODO
* @Author ZhangJun
* @Date  2025/3/12 15:03
**/
<template>
 <el-card class="text-left">
   <template #header>
     <div>子应用1测试修改全局状态</div>
   </template>

   <div>
     <div>当前全局状态:</div>
     <div class="bg-blue-lighter">
       <el-input
           v-model="globalStateCache"
           style="width: 240px"
           :autosize="{ minRows: 2, maxRows: 4 }"
           type="textarea"
           placeholder="请输入新的全局状态"
       />
     </div>
   </div>
   <el-button style="margin-top: 10px" type="primary" @click="changeGlobalState()">修改全局状态</el-button>
 </el-card>
</template>

<script setup lang="ts">
import {inject, ref} from "vue";

const mainAppProps:any = inject('MAIN_APP_PROPS')

//全局状态缓存
const globalStateCache = ref('')

//监听全局状态变化
mainAppProps?.onGlobalStateChange((state:any,prev:any) => {
  if(JSON.stringify(state)!== JSON.stringify(prev)){
    globalStateCache.value = JSON.stringify(state)
  }
})

/**
 * 全局状态的修改
 */
const changeGlobalState = () => {
  let updateState = JSON.parse(globalStateCache.value)
  //更新全局状态
  mainAppProps?.setGlobalState(updateState)
}

</script>

<style scoped>
.bg-blue-lighter{
  background-color: #f0f9ff;
  color: #4a4a4a;
}
</style>

四、使用 Pinia 实现子应用独立状态管理

如果子应用需要独立管理状态,可以使用Pinia(推荐)或Vuex

1. 安装 Pinia

在子应用中安装Pinia

npm install pinia

2. 配置 Pinia

在子应用中创建Pinia实例并注入到应用中。

// subApp1/src/main.ts
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';

let instance = null;

function render(props = {}) {
  const { container } = props;
  const app = createApp(App);
  const pinia = createPinia();

  app.use(pinia);
  app.use(router);
  instance = app.mount(container ? container.querySelector('#app') : '#app');
}

if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap() {
  console.log('subApp1 bootstrap');
}

export async function mount(props) {
  console.log('subApp1 mount');
  render(props);
}

export async function unmount() {
  console.log('subApp1 unmount');
  instance.unmount();
  instance = null;
}

3. 创建 Pinia Store

在子应用中创建Pinia Store

// subApp1/src/stores/userStore.js
import { defineStore } from 'pinia';

export const useUserStore = defineStore('user', {
  state: () => ({
    name: 'SubApp1 User',
  }),
  actions: {
    updateName(newName) {
      this.name = newName;
    },
  },
});

4. 在组件中使用 Pinia Store

<!-- subApp1/src/App.vue -->
<template>
  <div>
    <h1>{{ userStore.name }}</h1>
    <button @click="updateName">Update Name</button>
  </div>
</template>

<script>
import { useUserStore } from './stores/userStore';

export default {
  setup() {
    const userStore = useUserStore();

    const updateName = () => {
      userStore.updateName('New SubApp1 User');
    };

    return {
      userStore,
      updateName,
    };
  },
};
</script>

五、使用 EventBus 实现子应用通信

如果子应用之间需要通信,可以使用EventBus

在主应用中创建一个全局事件总线,并将其注入到子应用中。

1. 创建 EventBus

在主应用中创建一个eventBus.js文件,用于导出事件总线实例。

// src/eventBus.js
import mitt from 'mitt'
const eventBus = mitt()
export default eventBus;

2. 主应用注入事件总线

在主应用中,通过registerMicroAppsprops参数将事件总线传递给子应用。

// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { registerMicroApps, start } from 'qiankun';
import eventBus from './eventBus';

const app = createApp(App);
app.use(router);
app.mount('#app');

// 注册子应用
registerMicroApps([
  {
    name: 'subApp1',
    entry: '//localhost:7101',
    container: '#subapp-container',
    activeRule: '/subApp1',
    props: {
      eventBus, // 将事件总线传递给子应用
    },
  },
  {
    name: 'subApp2',
    entry: '//localhost:7102',
    container: '#subapp-container',
    activeRule: '/subApp2',
    props: {
      eventBus, // 将事件总线传递给子应用
    },
  },
]);

// 启动 qiankun
start();

3. 在子应用中使用 EventBus

在子应用中,通过props获取事件总线,并使用它来发送和接收事件。

3.1 子应用1 发送事件

在子应用1中,通过事件总线发送事件。

<!-- subApp1/src/views/Home.vue -->
<template>
  <div>
    <h1>子应用1</h1>
    <button @click="sendMessage">发送消息</button>
  </div>
</template>

<script>
import { inject } from 'vue';

export default {
  setup() {
    const props = inject('props');
    const eventBus = props.eventBus;

    const sendMessage = () => {
      eventBus.emit('message-from-subApp1', {
        message: 'Hello from SubApp1',
      });
    };

    return {
      sendMessage,
    };
  },
};
</script>

3.2 子应用2 监听事件

在子应用2中,通过事件总线监听事件。

<!-- subApp2/src/views/Home.vue -->
<template>
  <div>
    <h1>子应用2</h1>
    <p>收到消息:{{ message }}</p>
  </div>
</template>

<script>
import { inject, ref, onMounted, onUnmounted } from 'vue';

export default {
  setup() {
    const props = inject('props');
    const eventBus = props.eventBus;
    const message = ref('');

    const handleMessage = (payload) => {
      message.value = payload.message;
    };

    onMounted(() => {
      eventBus.on('message-from-subApp1', handleMessage);
    });

    onUnmounted(() => {
      eventBus.off('message-from-subApp1', handleMessage);
    });

    return {
      message,
    };
  },
};
</script>

六、总结

  • 全局状态共享:使用 qiankuninitGlobalState 方法。
  • 子应用独立状态管理:使用 PiniaVuex
  • 子应用通信:使用 EventBusCustomEvent

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程---多客户端服务器

写一个服务器和两个客户端 运行服务器和2个客户端&#xff0c;实现聊天功能 客户端1 和 客户端2 进行聊天 客户端1将聊天数据发送给服务器 服务器将聊天数据转发给客户端2 要求&#xff1a; 服务器使用 select 模型实现 客户端1使用 poll 模型实现 客户端2使用 多线程实现…

LeetCode 2614.对角线上的质数:遍历(质数判断)

【LetMeFly】2614.对角线上的质数&#xff1a;遍历(质数判断) 力扣题目链接&#xff1a;https://leetcode.cn/problems/prime-in-diagonal/ 给你一个下标从 0 开始的二维整数数组 nums 。 返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数&…

红日靶场(二)——个人笔记

靶场搭建 新增VMnet2网卡 **web&#xff1a;**需要配置两张网卡&#xff0c;分别是外网出访NAT模式和内网域环境仅主机模式下的VMnet2网卡。 **PC&#xff1a;**跟web一样&#xff0c;也是需要配置两张网卡&#xff0c;分别是外网出访NAT模式和内网域环境仅主机模式下的VMn…

实时视频分析的破局之道:蓝耘 MaaS 如何与海螺 AI 视频实现高效协同

一、蓝耘 MaaS 平台&#xff1a;AI 模型全生命周期管理的智能引擎 蓝耘 MaaS&#xff08;Model-as-a-Service&#xff09;平台是由蓝耘科技推出的 AI 模型全生命周期管理平台&#xff0c;专注于为企业和开发者提供从模型训练、推理到部署的一站式解决方案。依托云原生架构、高…

走进Java:String字符串的基本使用

❀❀❀ 大佬求个关注吧~祝您开心每一天 ❀❀❀ 目录 一、什么是String 二、如何定义一个String 1. 用双引号定义 2. 通过构造函数定义 三、String中的一些常用方法 1 字符串比较 1.1 字符串使用 1.2 字符串使用equals() 1.3 使用 equalsIgnoreCase() 1.4 cpmpareTo…

python系列之元组(Tuple)

不为失败找理由&#xff0c;只为成功找方法。所有的不甘&#xff0c;因为还心存梦想&#xff0c;所以在你放弃之前&#xff0c;好好拼一把&#xff0c;只怕心老&#xff0c;不怕路长。 python系列之元组&#xff08;Turple&#xff09; 一、元组是什么&#xff1f;——给新手的…

破解验证码新利器:基于百度OCR与captcha-killer-modified插件的免费调用教程

破解验证码新利器&#xff1a;基于百度OCR与captcha-killer-modified插件的免费调用教程 引言 免责声明&#xff1a; 本文提供的信息仅供参考&#xff0c;不承担因操作产生的任何损失。读者需自行判断内容适用性&#xff0c;并遵守法律法规。作者不鼓励非法行为&#xff0c;保…

批量删除 PPT 中的所有图片、某张指定图片或者所有二维码图片

PPT 文档中的图片如何删除呢&#xff1f;相信很多小伙伴或碰到类似的需求。比如我们需要删除 PPT 文档中的某一张图片或者某张二维码图片&#xff0c;如果每一页都有这张图片&#xff0c;或者有很多 ppt 都有同一张要删除的图片&#xff0c;我们应该怎么快速的完成删除呢&#…

大模型开发(六):LoRA项目——新媒体评论智能分类与信息抽取系统

LoRA项目——新媒体评论智能分类与信息抽取系统 0 前言1 项目介绍1.1 项目功能1.2 技术原理1.3 软硬件环境1.4 项目结构 2 数据介绍与处理2.1 数据集介绍2.2 数据处理2.3 数据导入器 3 模型训练3.1 配置文件3.2 工具函数3.3 模型训练3.4 模型评估 4 模型推理 0 前言 微调里面&…

mysql-innodb存储引擎主键索引叶子结点数据结构(非单纯的双向链表)

我们应该清楚行记录是放在页中的。 compact行记录格式&#xff1a; 主要介绍几个比较重要的参数 heap_no&#xff1a; 页号 record_type&#xff1a; 0 表示普通类型&#xff08;叶子结点&#xff09;&#xff0c;1表示B树的非叶子节点 &#xff0c;2 表示最小记录&#xff…

物联网为什么用MQTT不用 HTTP 或 UDP?

先来两个代码对比&#xff0c;上传温度数据给服务器。 MQTT代码示例 // MQTT 客户端连接到 MQTT 服务器 mqttClient.connect("mqtt://broker.server.com:8883", clientId) // 订阅特定主题 mqttClient.subscribe("sensor/data", qos1) // …

Vmware中的centos7连接上网

有很多刚刚开始配置了centos7&#xff0c;然后发现不能上网现在来解决这个问题。 测试能不能上网 先还原这个设置&#xff0c;如果没有动过的话就不用&#xff0c;连接模式是NAT模式 然后进去设置网络环境&#xff0c;记得是用超级用户设置 vi /etc/sysconfig/network-script…

【AI知识】常见的优化器及其原理:梯度下降、动量梯度下降、AdaGrad、RMSProp、Adam、AdamW

常见的优化器 梯度下降&#xff08;Gradient Descent, GD&#xff09;局部最小值、全局最小值和鞍点凸函数和非凸函数动量梯度下降&#xff08;Momentum&#xff09;自适应学习率优化器AdaGrad&#xff08;Adaptive Gradient Algorithm&#xff09;​RMSProp&#xff08;Root M…

线性规划的标准形式

标准形式的定义 目标函数&#xff1a;最大化线性目标函数 其中&#xff0c;x 是决策变量向量&#xff0c;c 是目标系数向量。 约束条件&#xff1a;等式形式约束 A x b, 其中&#xff0c;A 是约束系数矩阵&#xff0c;b 是常数项向量。 变量非负约束&#xff1a; 。 因此…

网络安全应急入门到实战

奇安信&#xff1a;95015网络安全应急响应分析报告&#xff08;2022-2024年&#xff09;官网可以下载 https://github.com/Bypass007/Emergency-Response-Notes 应急响应实战笔记 网络安全应急响应技术实战指南 .pdf 常见场景 第4章 勒索病毒网络安全应急响应 第5章 挖矿木…

应用程序安全趋势:左移安全、人工智能和开源恶意软件

软件是大多数行业业务运营的核心&#xff0c;这意味着应用程序安全从未如此重要。 随着组织采用云原生架构、微服务和开源组件&#xff0c;攻击面不断扩大。结果是&#xff1a;攻击者渴望利用的易受攻击和恶意依赖项数量不断增加。 2025 年&#xff0c;安全团队将面临日益复杂…

ospf动态路由

一、为什么使用动态路由 OSPF&#xff08;open shortest path first开放最短路径优先&#xff09;是内部网关协议(IGP)的一种&#xff0c;基于链路状态算法(LS)。 OSPF企业级路由协议(RFC2328 OSPFv2)&#xff0c;核心重点协议 OSPF共三个版本&#xff0c;OSPFV1主要是实验室…

基于单片机控制的电动汽车双闭环调速系统(论文+源码)

2.1系统方案 在本次设计中&#xff0c;其系统整个框图如下图3.1所示&#xff0c;其主要的核心控制模块由电源供电模块&#xff0c;晶振电路&#xff0c;驱动电路模块&#xff0c;霍尔传感器&#xff0c;按键模块&#xff0c;复位电路&#xff0c;LCD液晶显示及直流电机等组成。…

【病毒分析】伪造微软官网+勒索加密+支付威胁,CTF中勒索病毒解密题目真实还原!

1.背景 该CTF挑战题目完整复现了黑客的攻击链路&#xff0c;攻击者通过伪造钓鱼页面引导受害者下载恶意软件。用户访问伪造的 Microsoft 365 官网后&#xff0c;在点击“Windows Installer (64-bit)”下载选项时&#xff0c;页面会自动跳转至伪造的 GitHub 项目链接&#xff0…

PDF Reader Pro for Mac v4.9.0 PDF编辑/批注/OCR/转换工具 支持M、Intel芯片

PDF Reader Pro 是一款用户必备的集管理、编辑、转换、阅读功能于一体的专业的全能PDF阅读专家。快速、易用、强大&#xff0c;让您出色完成 PDF 工作。 应用介绍 PDF Reader Pro&#xff0c;一款功能齐全且强大的PDF阅读和编辑软件。支持PDF阅读、批注、PDF编辑、PDF格式转换…