概念
使用框架:qiankun
介绍:
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
qiankun官网:Go
当使用 iframe 整合系统时,假设我们有系统 A, 当我们想把系统 B 引入 A 系统时,只需要 B 系统提供一个 url 给 A 系统引用即可,这里我们把 A 系统叫做父应用,把 B 系统叫做子应用。同样的,微前端也延续了这个概念,微前端在使用起来基本和使用 iframe 一样平滑。
结构:
分为:主应用(父),微应用(子)
图1:
使用案例:
目标:
点击one按钮,切换到one微应用
点击two按钮,切换到two微应用
并且每个微应用都可以跳转自己的路由
步骤:
- 创建主应用项目
- 创建微应用项目
- 将微应用挂到主应用项目中
1. 在主应用中安装qiankun框架
$ yarn add qiankun # 或者 npm i qiankun -S
2. 在 主应用 中注册微应用
main.js:
import{ createApp }from'vue'import App from'./App.vue'import router from'./router/index'import ElementPlus from'element-plus'import'element-plus/dist/index.css'import{ registerMicroApps, start }from'qiankun';registerMicroApps([{name:"vueChildOne",props:{age:10},//给子应用传数据entry:"//localhost:3001",//默认会加载这个html,解析里面的js,动态执行(子应用必须支持跨域)里面,是用fetch去请求的数据container:"#child-one-content",//挂载到主应用的哪个元素下activeRule:"/child-one",//当我劫持到路由地址为//child-one时,我就把http://localhost:3001这个应用挂载到#child-one-content的元素下},{name:'vueChildTwo',entry:'//localhost:3002',// entry: { scripts: ['//http://192.168.2.120:3001/main.js'] },container:'#child-two-content',activeRule:'/child-two',},]);// start(); // 启动qiankun,这里不在一开始的时候使用createApp(App).use(ElementPlus).use(router).mount('#app-base')
App.vue
<template><div><div class="bens"><el-button type="primary" @click="$router.push('/child-one')">childOne</el-button><el-button type="primary" @click="$router.push('/child-two')">childTwo</el-button></div><router-view></router-view></div></template><script>exportdefault{name:"App",components:{},};</script><style>.bens {width:100%;display: flex;
justify-content: center;position: absolute;top: 15px;left:0;
z-index:9999999;}
#app-base {
font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
text-align: center;color: #2c3e50;
margin-top: 60px;}</style>
index.html:
// 将id:app 改为 app-base 自定义就行,只要与main.js对应起来,切不与微应用重复<div id="app-base"></div>
router.js
import{ createRouter, createWebHistory }from"vue-router";// 2. 配置路由const routes =[{path:'/child-one',component:()=>import('@/views/childOne/index.vue'),},{path:'/child-two',component:()=>import('@/views/childTwo/index.vue'),},];// 1.返回一个 router 实列,为函数,里面有配置项(对象) historyconst router =createRouter({history:createWebHistory(),
routes,});// 3导出路由 然后去 main.ts 注册 router.tsexportdefault router
childOne/index.vue
<template><h2>我是 主应用 one</h2><div id="child-one-content"></div></template><script>import{ start }from"qiankun";exportdefault{name:"childOne",components:{},mounted(){// 启动微应用if(!window.qiankunStarted){
window.qiankunStarted =true;start();}},};</script><style></style>
childTwo/index.vue
<template><h2>我是 主应用 two</h2><div id="child-two-content"></div></template><script>import{ start }from"qiankun";exportdefault{name:"childTwo",components:{},mounted(){// 启动微应用if(!window.qiankunStarted){
window.qiankunStarted =true;start();}},};</script><style></style>
4. 微应用配置child-one
src下创建public-path.js
if(window.__POWERED_BY_QIANKUN__){
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
main.js
import{ createApp }from'vue'import App from'./App.vue'import router from'./router/index'import'./public-path'// 引入public-path.js// createApp(App).mount('#app')let instance =null;functionrender(props ={}){if(instance)return;const{ container }= props;
console.log(container);
instance =createApp(App).use(router).mount(container ? container.querySelector("#app-child-one"):"#app-child-one");}// 独立运行时if(!window.__POWERED_BY_QIANKUN__){render();}exportasyncfunctionbootstrap(){
console.log("[vue] vue app bootstraped");}exportasyncfunctionmount(props){
console.log("[vue] props from main framework", props);render(props);}exportasyncfunctionunmount(){//可选链操作符
instance.$destroy?.();
instance =null;}
index.html
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1.0"><link rel="icon" href="<%= BASE_URL %>favicon.ico"><title><%= htmlWebpackPlugin.options.title %></title></head><body><noscript><strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app-child-one"></div><!-- built files will be auto injected --></body></html>
vue.config.js
module.exports ={lintOnSave:false,devServer:{port:"3001",headers:{"Access-Control-Allow-Origin":"*",//所有人都可以访问我的服务器},},configureWebpack:{output:{// library: `${name}-[name]`,library:`vueChildOne`,libraryTarget:"umd",// 把微应用打包成 umd 库格式// jsonpFunction: `webpackJsonp_${name}`,},},};
router.js
import{ createRouter, createWebHashHistory, createWebHistory }from"vue-router";// 2. 配置路由const routes =[{path:'/',component:()=>import('@/views/home/index.vue'),},{path:'/about',component:()=>import('@/views/about/index.vue'),},];// 1.返回一个 router 实列,为函数,里面有配置项(对象) historyconst router =createRouter({history:createWebHashHistory('/child-one'),
routes,});// 3导出路由 然后去 main.ts 注册 router.tsexportdefault router
5. 微应用配置child-two
与child-two同理,只要把对应的" child-one " 换成" child-two "即可
demo代码地址
码云地址
版权归原作者 野克 所有, 如有侵权,请联系我们删除。