qiankun(乾坤) - Vue - 嵌套使用 — 解决业务场景
目前有项目 A,内部注册了项目 B,项目 B也使用了 qiankun,内部注册了项目 C
项目A — qk-a(主应用)
main.js
import Vue from 'vue'
import App from './App.vue'
import { registerMicroApps, start } from 'qiankun';
import router from './router'
Vue.config.productionTip = false
// 由于本身有window.__POWERED_BY_QIANKUN__参数,sub应用无法判断自己在第几层
// 设置一个全局参数,让sub应用检测到该参数则说明自己作为孙子应用运行
window.__POWERED_BY_QIANKUN_PARENT__ = true // 核心代码
// 常规注册微应用
registerMicroApps([{
name: 'qk-b',
entry: '//localhost:8082/',
activeRule: '/qk-b',
container: '#qk-b-container', // 子应用挂载的div
},
]);
start();
new Vue({
router ,
render: h => h(App),
}).$mount('#app')
项目B — qk-b
main.js
import { registerMicroApps, start, } from 'qiankun'
import VueRouter from 'vue-router'
import Vue from 'vue'
import App from './App'
Vue.use(VueRouter)
let router = null;
let instance = null;
let flag = false;
function render(props = {}) {
const { container } = props;
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN_PARENT__ ? '/qk-b/' : '/',
mode: 'history',
routes:[]
});
// 根据业务情况进行实际使用
// const childRoute = ['/qk-b'];
// const isChildRoute = path => childRoute.some(item => path.startsWith(item))
// const rawAppendChild = HTMLHeadElement.prototype.appendChild;
// const rawAddEventListener = window.addEventListener;
// router.beforeEach((to, from, next) => {
// // 从子项目跳转到主项目
// if(isChildRoute(from.path) && !isChildRoute(to.path)){
// HTMLHeadElement.prototype.appendChild = rawAppendChild;
// window.addEventListener = rawAddEventListener;
// }
// next();
// });
instance = new Vue({
router,
render: h => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
if(!flag){
// 应用B类注册微应用
registerMicroApps([
{
name: 'qk-c',
entry: 'http://localhost:8083',
container: '#qk-c-container', // 容器为应用B内部定义
activeRule: window.__POWERED_BY_QIANKUN_PARENT__ ? '/qk-b/qk-c' : '/qk-c', // 根据在应用A内进行申请的变量进行判断
}
]);
start();
flag = true
}
}
if (!window.__POWERED_BY_QIANKUN_PARENT__) {
render();
}
export async function bootstrap() {
console.log('vue app bootstraped');
}
export async function mount(props) {
render(props);
}
export async function unmount() {
instance.$destroy();
instance = null;
router = null;
}
vue.config.js
const { name } = require('./package.json')
module.exports = {
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
}
},
devServer: {
port: 8082,
headers: {
'Access-Control-Allow-Origin': '*' // 主应用获取子应用时跨域响应头
}
}
}
项目C — qk-c
main.js
import './public-path'
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
let instance = null
function render(props = {}) {
const { container } = props;
instance = new Vue({
router,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
// 解决加载资源是404的问题
if (window.__POWERED_BY_QIANKUN__) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
render(props);
}
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
}
vue.config.js
// package.json的name需注意与主应用一致
const { name } = require('./package.json')
module.exports = {
lintOnSave: false,
configureWebpack: {
output: {
library: `${name}`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
}
},
devServer: {
port: 8083,
headers: {
'Access-Control-Allow-Origin': '*' // 主应用获取子应用时跨域响应头
}
},
}
以上均为核心代码,具体demo可点击以下地址