vue3+ts+MicroApp實(shí)戰(zhàn)教程
項(xiàng)目準(zhǔn)備
1、基于amin-work-x項(xiàng)目作為原始項(xiàng)目,改造動(dòng)態(tài)菜單為自定義菜單
2、分別在主應(yīng)用項(xiàng)目(main)和子應(yīng)用(childrenOne,childrenTwo)項(xiàng)目中安裝microApp
npm i @micro-zoe/micro-app --save
子項(xiàng)目配置
1,修改子項(xiàng)目mian.ts,添加與基座的交互配置和路由沖突解決
import { createApp } from "vue"; import App from "./App.vue"; import { Router } from 'vue-router' import router from "./router"; import "./utils/router"; import ElementPlus from "element-plus"; import "element-plus/dist/index.css"; import "dayjs/locale/zh-cn"; import zhCn from "element-plus/es/locale/lang/zh-cn"; import "@/icons/iconfont/iconfont.css"; import "@/icons/iconfont/iconfont.js"; import "@/styles/main.css"; import LayoutStore from "@/layouts"; import http from "@/api/http"; import { registerComponents } from "./components"; import * as Icons from "@element-plus/icons"; import pinia from "./store/pinia"; import "./setting"; declare global { interface Window { microApp: any __MICRO_APP_NAME__: string __MICRO_APP_ENVIRONMENT__: string __MICRO_APP_BASE_ROUTE__: string } } // 與基座進(jìn)行數(shù)據(jù)交互 function handleMicroData(router: Router) { // 是否是微前端環(huán)境 if (window.__MICRO_APP_ENVIRONMENT__) { // 監(jiān)聽基座下發(fā)的數(shù)據(jù)變化 window.microApp.addDataListener((data: Record<string, unknown>) => { console.log('child-vue3 addDataListener:', data) // 當(dāng)基座下發(fā)path時(shí)進(jìn)行跳轉(zhuǎn) if (data.path && data.path !== router.currentRoute.value.path) { router.push(data.path as string) } }) // 向基座發(fā)送數(shù)據(jù) setTimeout(() => { window.microApp.dispatch({ myname: 'tenant-app' }) }, 3000) } } /** * 用于解決主應(yīng)用和子應(yīng)用都是vue-router4時(shí)相互沖突,導(dǎo)致點(diǎn)擊瀏覽器返回按鈕,路由錯(cuò)誤的問(wèn)題。 * 相關(guān)issue:https://github.com/micro-zoe/micro-app/issues/155 * 當(dāng)前vue-router版本:4.0.12 */ function fixBugForVueRouter4(router: Router) { // 判斷主應(yīng)用是main-vue3或main-vite,因?yàn)檫@這兩個(gè)主應(yīng)用是 vue-router4 if (window.__MICRO_APP_ENVIRONMENT__) { //if (window.location.href.includes('/main-vue3') || window.location.href.includes('/main-vite')) { /** * 重要說(shuō)明: * 1、這里主應(yīng)用下發(fā)的基礎(chǔ)路由為:`/main-xxx/app-vue3`,其中 `/main-xxx` 是主應(yīng)用的基礎(chǔ)路由,需要去掉,我們只取`/app-vue3`,不同項(xiàng)目根據(jù)實(shí)際情況調(diào)整 * * 2、realBaseRoute 的值為 `/app-vue3` */ const realBaseRoute = window.__MICRO_APP_BASE_ROUTE__;//.replace(/^\/app-tenant-[^/]+/g, '') router.beforeEach(() => { if (typeof window.history.state?.current === 'string') { window.history.state.current = window.history.state.current.replace(new RegExp(realBaseRoute, 'g'), '') } }) router.afterEach(() => { if (typeof window.history.state === 'object') { window.history.state.current = realBaseRoute + (window.history.state.current || '') } }) } } const app = createApp(App); Object.keys(Icons).forEach((it) => { app.component(it, (Icons as any)[it]); }); registerComponents(app); app.use(LayoutStore, { state: { layoutMode: "ltr", }, actions: { onPersonalCenter() { router.push({ path: "/personal", query: { uid: 1 } }); }, onLogout() { router.replace({ path: "/login", query: { redirect: "/" } }).then(() => { window.location.reload(); }); }, }, }); app.use(pinia).use(router); app.use(ElementPlus, { locale: zhCn, }); app.use(http); app.mount("#app"); handleMicroData(router) fixBugForVueRouter4(router) // 監(jiān)聽卸載操作 window.addEventListener('unmount', function () { //console.log("r4開始卸載", window.location, window.history, app) app?.unmount() //console.log('微應(yīng)用child-vue3卸載了') })
2,修改vue.config.js文件,配置publicPath、端口號(hào)、允許跨域
3,為保證子應(yīng)用的路由在主應(yīng)用中能直接使用,可在每個(gè)路由前添加子應(yīng)用的路由標(biāo)志
這一步可不操作,如果不添加,則需要在主應(yīng)用添加菜單或者動(dòng)態(tài)獲取菜單時(shí),根據(jù)其他標(biāo)志,為路由手動(dòng)加上當(dāng)前子應(yīng)用的標(biāo)志,用于判斷子應(yīng)用來(lái)源
4、修改子應(yīng)用路由問(wèn)history模式
const router = createRouter({ history: createWebHistory(window.__MICRO_APP_BASE_ROUTE__||process.env.BASE_URL), routes: mapTwoLevelRouter([...constantRoutes, ...asyncRoutes]), });
主應(yīng)用項(xiàng)目配置
1,在layout中添加子應(yīng)用入口文件(src\layouts\microapp\app-one.vue)
<template> <div style="height: 100%"> <micro-app name="appname-one" :url="url" baseroute="/app-main" :data="microAppData" @created="handleCreate" @beforemount="handleBeforeMount" @mounted="handleMount" @unmount="handleUnmount" @error="handleError" @datachange="handleDataChange" style="height: 100%" ></micro-app> </div> </template> <script lang="ts"> export default { name: "name-app", data() { return { url: process.env.NODE_ENV === "development" ? "http://localhost:4009/app-one" : "通過(guò)配置獲取線上地址", microAppData: { msg: "來(lái)自基座的數(shù)據(jù)" }, }; }, methods: { handleCreate(): void { console.log("child-vue3 創(chuàng)建了"); }, handleBeforeMount(): void { console.log("child-vue3 即將被渲染"); }, handleMount(): void { console.log("child-vue3 已經(jīng)渲染完成"); setTimeout(() => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this.microAppData = { msg: "來(lái)自基座的新數(shù)據(jù)" }; }, 2000); }, handleUnmount(): void { console.log("child-vue3 卸載了"); }, handleError(): void { console.log("child-vue3 加載出錯(cuò)了"); }, handleDataChange(e: CustomEvent): void { console.log("來(lái)自子應(yīng)用 child-vue3 的數(shù)據(jù):", e.detail.data); }, }, }; </script> <style></style>
2,在主應(yīng)用中注冊(cè)子應(yīng)用路由
子應(yīng)用的路由第一次指向主應(yīng)用的layout,第二層指向上面新建的入口文件
3,修改主應(yīng)用publicPath
此處的publicPath需與app-one中的baseroute保持一致
配置完成后,先后運(yùn)行兩個(gè)項(xiàng)目后,在主應(yīng)用中手動(dòng)添加一個(gè)子應(yīng)用的的具體頁(yè)面路由,就可以在主應(yīng)用中打開子應(yīng)用了,但是此時(shí)子應(yīng)用的路由表覆蓋了主應(yīng)用。
為解決這個(gè)問(wèn)題,需要在子應(yīng)用中添加一個(gè)非layout布局的空頁(yè)面,當(dāng)子應(yīng)用單獨(dú)運(yùn)行時(shí),指向layout布局頁(yè)面,如果是在微服務(wù)中使用,則指向空頁(yè)面
src\layouts\EmptyLayout.vue
<template> <div class="empty-layout"> <router-view> </router-view> </div> </template> <style lang="scss" scoped> .empty-layout { height: 100%; } </style>
src\router\index.ts
到此這篇關(guān)于vue3+ts+MicroApp實(shí)戰(zhàn)教程的文章就介紹到這了,更多相關(guān)vue3 ts MicroApp內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解如何從零開始搭建Express+Vue開發(fā)環(huán)境
這篇文章主要介紹了詳解如何從零開始搭建Express+Vue開發(fā)環(huán)境,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07Vue使用Vue-cropper實(shí)現(xiàn)圖片裁剪
這篇文章主要為大家詳細(xì)介紹了Vue使用Vue-cropper實(shí)現(xiàn)圖片裁剪,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05vue中跳轉(zhuǎn)界面的3種實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于vue中跳轉(zhuǎn)界面的3種實(shí)現(xiàn)方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07vue學(xué)習(xí)記錄之動(dòng)態(tài)組件淺析
動(dòng)態(tài)組件指的是動(dòng)態(tài)切換組件的顯示與隱藏,這篇文章主要給大家介紹了關(guān)于vue學(xué)習(xí)記錄之動(dòng)態(tài)組件的相關(guān)資料,本文通過(guò)示例代碼介紹介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10vue awesome swiper異步加載數(shù)據(jù)出現(xiàn)的bug問(wèn)題
這篇文章主要介紹了vue awesome swiper異步加載數(shù)據(jù)出現(xiàn)的bug問(wèn)題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07