Vue中使用乾坤(qiankun)微应用开发多应用
| 方法 | 参数 | 值 | 备注 |
|---|---|---|---|
| registerMicroApps <Array> | name ✅ | sub-app | 微应用的名称 |
| entry ✅ | //localhost:4001 | 子应用地址 | |
| container ✅ | #subapp-viewport | 微应用的容器节点选择器 | |
| activeRule ✅ | /vue | 微应用的激活规则(子应用路由history规则) | |
| props:{ globalState updateState } | globalState updateState | globalState:传递数据 updateState:传递修改方法 ✅ 核心 | |
| start <Objct> | sandbox : {} | strictStyleIsolation: true | 样式隔离 |
| setDefaultMountApp | '/homeApp' | 设置主应用启动后默认进入的微应用 | |
$ yarn add qiankun # 或者 npm i qiankun -S
// main.js import { registerMicroApps, start } from "qiankun"; // 自己维护全局状态(不依赖 qiankun) const globalState = { user: { name: "admin", role: "admin" }, token: "123456", }; // 定义修改方法(子应用也能调用) function updateState(state) { Object.assign(globalState, state); // 派发事件,所有应用同步更新 window.dispatchEvent(new CustomEvent("stateChange", { detail: globalState })); } // 注册子应用 registerMicroApps([ { name: "sub-app", // 子应用名称 entry: "//localhost:4001", // 子应用地址 container: "#subapp-viewport", // EL容器 activeRule: "/vue", //子应用路由history规则 [ history: createWebHistory("/vue")] props: { globalState, // 传递数据 updateState, // 传递修改方法 ✅ 核心 }, }, ]); // 启动应用 start({ // 样式沙箱 sandbox: { // 🌈 关闭严格隔离(关闭 Shadow DOM) strictStyleIsolation: false, // ✅ 开启:实验性样式隔离(推荐!动态加前缀,类似 Vue scoped) experimentalStyleIsolation: true, }, });
// App.vue <template> <h1>主应用</h1> <p>{{ user.name }} , {{ user.role }} , {{ token }}</p> <button @click="change">主应用修改数据</button> <router-view></router-view> <!-- 导航 --> <div style="margin:10px 0"> <router-link to="/">首页</router-link> | <router-link to="/vue">子应用 Vue3</router-link> | <router-link to="/vue2">子应用 Vue2</router-link> </div> <div id="subapp-viewport"></div> </template> <script setup> import { ref } from "vue"; const user = ref({}); const token = ref(""); // 监听数据更新 window.addEventListener("stateChange", (e) => { console.log(e.detail); user.value = e.detail.user; token.value = e.detail.token; }); // 更新数据 const change = () => { window.dispatchEvent( new CustomEvent("stateChange", { detail: { user: { name: "主应用更新啦", role: "role-main" }, token: "new-token", }, }), ); }; </script>
// router.js import { createRouter, createWebHistory } from "vue-router"; import Home from "./components/Home.vue"; const routes = [ { path: "/", component: Home }, // 子应用路由占位(自动匹配) { path: "/vue/:pathMatch(.*)*", component: { render: () => null } }, // { path: '/vue2/:pathMatch(.*)*', component: { render: () => null } } ]; const router = createRouter({ history: createWebHistory(), routes, }); export default router;
npm install vite-plugin-qiankun --save-dev
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import qiankun from "vite-plugin-qiankun";
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
// ✅ 注册微前端子应用
qiankun("sub-app", {
useDevMode: true, // 禁用 Vite 热更新(HMR),以避免与 qiankun 的沙箱机制冲突,确保子应用能正确注册并被主应用加载
}),
],
server: {
port: 4001,
host: "0.0.0.0",
cors: true, // ✅ 子应用开启跨域
origin: "http://localhost:4001",
},
});
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import {
renderWithQiankun,
qiankunWindow,
} from "vite-plugin-qiankun/dist/helper";
let app = null;
// 渲染函数
function render(props = {}) {
const { container } = props;
console.log(props, "render"); // 获取主应用传入子应用数据
app = createApp(App);
app.use(router);
app.mount(container ? container.querySelector("#app") : "#app");
// 将通信方法挂载到全局
window.$qiankun = props;
}
// 独立运行时直接渲染
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
render();
}
// qiankun 生命周期
renderWithQiankun({
// 挂载时触发
// 用于初始化子应用的状态
mount(props) {
render(props);
},
// 只有子应用第一次加载会触发
bootstrap() {},
// 卸载时触发
// 用于清理子应用的状态和事件
unmount() {
app.unmount();
},
});
export { render };
<template>
<h2>🧩 子应用 A</h2>
<p>🌈接收数据:{{ user?.name }}</p>
<button @click="updateSub">子应用修改全局数据</button>
<div @click="goAbout" style="padding: 10px; background: #ccc; width: 300px;">
去关于我们页面
</div>
<router-view></router-view>
</template>
<script setup>
import { ref, onMounted, nextTick } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
const user = ref({});
onMounted(async () => {
// 等待 nextTick 确保子应用状态更新完成
await nextTick();
// 从全局状态中获取用户信息
user.value = window.$qiankun.globalState?.user;
});
// 子应用修改全局数据
const updateSub = () => {
window.$qiankun.updateState({
user: { name: "子应用A修改成功", role: "role-child" },
token: "token-999",
});
};
// 去关于我们页面
const goAbout = () => {
router.push({
path: "/about",
query: {
id: "55555",
},
});
};
</script>
import { createRouter, createWebHistory } from "vue-router";
import Home from "./components/HelloWorld.vue";
export default createRouter({
history: createWebHistory("/vue"), // 🌈 必须和主应用 activeRule 一致
routes: [
{ path: "/", component: Home },
{ path: "/about", component: () => import("./components/About.vue") },
],
});
下载案例代码:下载按钮

浙公网安备 33010602011771号