一、创建主应用项目
(1)创建主应用
首先创建vue3项目,具体步骤就不说了,网上一大堆,这里给项目取名main
vue creat main
(2)安装qiankun
$ yarn add qiankun #
或者
npm i qiankun -S
(3)配置main.js(注册子应用)
子应用的名称设置为vueSub,跳转地址为/vueSub,渲染容器为id为subapp-container的元素(必须有该元素)
import { createApp } from 'vue';
import {
registerMicroApps, start,
} from 'qiankun';
import App from './App.vue';
import router from './router';
import store from './store';
import actions from './shared/actions';
createApp(App).use(store).use(router).mount('#main');
registerMicroApps([
{
name: 'vueSub', // 微应用的名称,微应用之间必须确保唯一。
entry: '//localhost:9002', // 必选,微应用的入口。
container: '#subapp-container', // 必选,微应用的容器节点的选择器或者 Element 实例。
activeRule: '/vueSub', // 必选,微应用的激活规则。
props: {
router, // 将主应用的路由传给子应用,子应用才能返回到主应用上
}, // 参数
},
]);
//设置默认进入的子应用
// setDefaultMountApp('/vue3');
start();
(4)在页面中配置子应用的渲染元素
在APP.vue中,我增加了个div,官方是使用router-view和router-link来进行主页面和子页面切换,但是我需要用的场景是主应用打开后,点击子应用的图标进入 子应用,之后在子应用中点击返回按钮返回到主应用界面,所以采用了以下的方式。
<template>
<div >
<router-view />
<div id="subapp-container"></div>
</div>
</template>
<style lang="stylus">
</style>
\
路由文件使用的就是创建后的例子,使用的history模式
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';
import Login from '../views/Login.vue';
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
二、创建子应用项目链接
(1)创建子应用,不需要导入qiankun
同样使用创建一个vue项目, 之前注册的名称加vueSub,这里也用这个名称,这里的名称不影响跳转,但是为了保持统一用一个,之后的配置打包里面需要和上面主应用的名称一致。
vue create vueSub
之后在创建一个文件public-path.js在main.js同级目录下,内容如下
这个主要解决的是子应用动态载入的脚本,样式,图片等地址不正确的问题。
//public-path.js
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
(2)配置main.js
在子应用中,需要将生命周期钩子暴露出来,引入上面创建的js
import './public-path';
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
let instance = null;
function render(props = {}) {
const { container } = props;
instance = createApp(App);
instance.use(store)
.use(router)
.mount(container ? container.querySelector('#app') : '#app');
//这里的app是在public/index.html里的div的id,和之前主应用了配置的无关
}
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
//暴露生命周期的三个函数
export async function bootstrap() {
console.log('%c ', 'color: green;', 'vue3.0 app bootstraped');
}
export async function unmount() {
instance.unmount();
instance._container.innerHTML = '';
instance = null;
}
export const mount = async (props) => {
console.log('子应用加载');
render(props);
};
(3)配置router.js
主要是history: 的配置,这里的vueSub要和主应用里配置的一致。
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';
const routes = [
{
path: '/',
name: 'Home',
component: Home,
children: [
{
path: '/about',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
name: '用户列表',
},
],
},
];
const router = createRouter({
base: '',
history: createWebHistory(window.__POWERED_BY_QIANKUN__ ? '/vueSub' : '/'),
routes,
});
export default router;
(4)配置vue.config.js
这里的配置重点是3个地方,一个是端口号,要和主应用的一致,library也要和主应用一致,最后是要配置跨域。 library: 'vueSub', port: 9002,
const path = require('path')
const { packageName } = require('./package')
function resolve (dir) {
return path.join(__dirname, dir)
}
module.exports = {
filenameHashing: true,
lintOnSave: process.env.NODE_ENV !== 'production',
runtimeCompiler: true,
productionSourceMap: false,
devServer: {
hot: true,
disableHostCheck: true,
port: 9002,//与主应用配置的一致
overlay: {
warnings: false,
errors: true
},
headers: {
"Access-Control-Allow-Origin": "*"
},
},
// 自定义webpack配置
configureWebpack: {
resolve: {
alias: {
'@': resolve('src')
}
},
output: {
// 把子应用打包成 umd 库格式
library: 'vueSub',//与主应用配置的一致
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${packageName}`
}
}
}
以上项目建完了,只要调用router的push就能进行跳转。具体看下一部分