因为项目主要是vue,就只练了vue,跟着这位大佬的文章练习的。
子应用创建
第一步:创建子应用sub-vue1,命令:vue create sub-vue1。
第二步:将router修改为routes,里面代码改为
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/about',
name: 'About',
component: () =>
import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
},
];
export default routes;
第三步:在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 { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
import routes from './routes';
import store from './store';
let router = null;
let instance = null;
// 如果不是乾坤环境,直接运行render,从而让子应用可以独立运行
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
// 这个函数可以学学怎么用的,加个颜色
console.log('%c ', 'color: green;', 'vue3.0 app bootstraped');
}
export async function mount(props) {
render(props);
}
export async function unmount() {
instance.unmount();
instance._container.innerHTML = '';
instance = null;
router = null;
}
// todo: 在乾坤调用 render 函数的时候,会附上一些信息,比如说容器的挂载节点等
function render(props = {}) {
const { container } = props;
router = createRouter({
// 如果是运行在乾坤的环境下,所有的路由路径会在开头加上/sub-vue
history: createWebHistory(window.__POWERED_BY_QIANKUN__ ? '/sub-vue' : '/'),
routes,
});
instance = createApp(App);
instance.use(router);
instance.use(store);
instance.mount(container ? container.querySelector('#app') : '#app');
}
第五步:修改vue.config.js,按照文章里会有一些版本报错,应该是我的webpack5问题,所以按照提示注释一些属性,还有没研究,挖一个坑,后期补吧。
const { name } = require('./package');
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
outputDir: 'dist',
assetsDir: 'static',
filenameHashing: true,
devServer: {
hot: true,
// disableHostCheck: true,
port: '8080',
// overlay: {
// warnings: false,
// errors: true,
// },
// clientLogLevel: 'warning',
compress: true,
headers: {
// 一定要加的,因为乾坤会用http的请求去获取子应用的代码,那么必然会出现跨域的问题。
'Access-Control-Allow-Origin': '*',
},
historyApiFallback: true,
},
configureWebpack: {
resolve: {
alias: {
'@': resolve('src'),
},
},
output: {
// 把子应用打包成 umd 库格式,从而主应用能够获取到子应用导出的生命周期钩子函数
library: `${name}-[name]`,
libraryTarget: 'umd',
// jsonpFunction: `webpackJsonp_${name}`,
},
},
};
第六步,可能会报__webpack_public_path__错误,那就在.eslintrc.js里加入
globals: {
__webpack_public_path__: true,
},
子应用注册
第一步:创建主应用,并安装乾坤 npm i qiankun -S;
vue create main
npm i qiankun -S
第二步:创建qiankun文件夹和index.js文件,结构如下:
import {
registerMicroApps,
runAfterFirstMounted,
setDefaultMountApp,
start,
} from 'qiankun';
/**
* Step1 注册子应用
*/
const microApps = [
{
name: 'sub-vue1',
developer: 'vue3.x',
entry: '//localhost:8080',
activeRule: '',//这里最最最最最重要,这个需要匹配子应用的路由!!!!!
},
];
const apps = microApps.map((item) => {
return {
...item,
container: '#subapp-container', // 子应用挂载的 div
props: {
developer: item.developer,
routerBase: item.activeRule,
},
};
});
// 子应用挂载的几个生命周期钩子
registerMicroApps(apps, {
beforeLoad: (app) => {
console.log('before load app.name====>>>>>', app.name);
},
beforeMount: [
(app) => {
console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name);
},
],
afterMount: [
(app) => {
console.log('[LifeCycle] after mount %c%s', 'color: green;', app.name);
},
],
afterUnmount: [
(app) => {
console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name);
},
],
});
/**
* Step2 设置挂载的子应用
*/
setDefaultMountApp('/sub-vue');
/**
* Step3 启动应用
*/
start();
runAfterFirstMounted(() => {
console.log('[MainApp] first app mounted');
});
export default apps;
第三步:修改主应用vue.config.js,也是有webpack5不兼容问题……
module.exports ={
lintOnSave: false,//关闭eslint报错
devServer: {
port: '8443',
// clientLogLevel: 'warning',
// disableHostCheck: true,
compress: true,
historyApiFallback: true,
},
}
第四步:修改一下主应用的APP.vue
//没有安装less的,安装一下less和less-loader
<template>
<div class="layout-wrapper">
<header class="layout-header">
<div class="logo">MSP</div>
</header>
<main class="layout-main">
<aside class="layout-aside">
<ul>
<li v-for="item in microApps" :key="item.name" @click="goto(item)">
{{ item.name }}
</li>
</ul>
</aside>
<section class="layout-section" id="subapp-container"></section>
</main>
</div>
</template>
<script>
import microApps from './qiankun';
export default {
name: 'App',
data() {
return {
isLoading: true,
microApps,
};
},
methods: {
goto(item) {
history.pushState(null, item.activeRule, item.activeRule);
},
},
};
</script>
<style lang="less">
* {
margin: 0;
padding: 0;
}
html,
body,
.layout-wrapper {
height: 100%;
overflow: hidden;
}
.layout-wrapper {
.layout-header {
height: 50px;
width: 100%;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
line-height: 50px;
position: relative;
.logo {
float: left;
margin: 0 50px;
}
.userinfo {
position: absolute;
right: 100px;
top: 0;
}
}
.layout-main {
height: calc(100% - 50px);
overflow: hidden;
display: flex;
justify-content: space-evenly;
.layout-aside {
width: 190px;
ul {
margin: 50px 0 0 20px;
border-right: 2px solid #aaa;
li {
list-style: none;
display: inline-block;
padding: 0 20px;
color: #aaa;
margin: 20px 0;
font-size: 18px;
font-weight: 400;
cursor: pointer;
&.active {
color: #42b983;
text-decoration: underline;
}
&:hover {
color: #444;
}
}
}
}
.layout-section {
width: 100%;
height: 100%;
}
}
}
</style>
最后成图: