17 changed files with 319 additions and 66 deletions
@ -1,8 +1,56 @@ |
|||||||
import Vue from 'vue' |
import Vue from 'vue' |
||||||
import App from './App.vue' |
import App from './App.vue' |
||||||
|
import VueRouter from 'vue-router'; |
||||||
|
|
||||||
Vue.config.productionTip = false |
Vue.config.productionTip = false |
||||||
|
let router = null; |
||||||
|
let instance = null; |
||||||
|
|
||||||
new Vue({ |
function render(props = {}) { |
||||||
render: h => h(App), |
const { container } = props; |
||||||
}).$mount('#app') |
router = new VueRouter({ |
||||||
|
base: window.__POWERED_BY_QIANKUN__ ? '/vue' : '/', |
||||||
|
mode: 'history', |
||||||
|
}); |
||||||
|
|
||||||
|
instance = new Vue({ |
||||||
|
router, |
||||||
|
render: h => h(App), |
||||||
|
}).$mount(container ? container.querySelector('#app') : '#app'); |
||||||
|
} |
||||||
|
|
||||||
|
if (!window.__POWERED_BY_QIANKUN__) { |
||||||
|
render(); |
||||||
|
} |
||||||
|
|
||||||
|
function storeTest(props) { |
||||||
|
props.onGlobalStateChange && |
||||||
|
props.onGlobalStateChange( |
||||||
|
(value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev), |
||||||
|
true, |
||||||
|
); |
||||||
|
props.setGlobalState && |
||||||
|
props.setGlobalState({ |
||||||
|
ignore: props.name, |
||||||
|
user: { |
||||||
|
name: props.name, |
||||||
|
}, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
export async function bootstrap() { |
||||||
|
console.log('[vue] vue app bootstraped'); |
||||||
|
} |
||||||
|
|
||||||
|
export async function mount(props) { |
||||||
|
console.log('[vue] props from main framework', props); |
||||||
|
storeTest(props); |
||||||
|
render(props); |
||||||
|
} |
||||||
|
|
||||||
|
export async function unmount() { |
||||||
|
instance.$destroy(); |
||||||
|
instance.$el.innerHTML = ''; |
||||||
|
instance = null; |
||||||
|
router = null; |
||||||
|
} |
||||||
|
@ -1,4 +1,39 @@ |
|||||||
const { defineConfig } = require('@vue/cli-service') |
const { defineConfig } = require('@vue/cli-service') |
||||||
|
|
||||||
|
const path = require('path'); |
||||||
|
const { name } = require('./package'); |
||||||
|
|
||||||
|
function resolve(dir) { |
||||||
|
return path.join(__dirname, dir); |
||||||
|
} |
||||||
|
|
||||||
|
const port = 7101; // dev port
|
||||||
|
|
||||||
module.exports = defineConfig({ |
module.exports = defineConfig({ |
||||||
transpileDependencies: true |
outputDir: 'dist', |
||||||
|
assetsDir: 'static', |
||||||
|
filenameHashing: true, |
||||||
|
|
||||||
|
transpileDependencies: true, |
||||||
|
devServer: { |
||||||
|
// host: '0.0.0.0',
|
||||||
|
hot: true, |
||||||
|
port, |
||||||
|
headers: { |
||||||
|
'Access-Control-Allow-Origin': '*', |
||||||
|
}, |
||||||
|
}, |
||||||
|
// 自定义webpack配置
|
||||||
|
configureWebpack: { |
||||||
|
resolve: { |
||||||
|
alias: { |
||||||
|
'@': resolve('src'), |
||||||
|
}, |
||||||
|
}, |
||||||
|
output: { |
||||||
|
// 把子应用打包成 umd 库格式
|
||||||
|
library: `${name}-[name]`, |
||||||
|
libraryTarget: 'umd' |
||||||
|
}, |
||||||
|
}, |
||||||
}) |
}) |
||||||
|
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
*微应用apps |
||||||
|
* @name: 微应用名称 - 具有唯一性 |
||||||
|
* @entry: 微应用入口.必选 - 通过该地址加载微应用, |
||||||
|
* @container: 微应用挂载节点 - 微应用加载完成后将挂载在该节点上 |
||||||
|
* @activeRule: 微应用触发的路由规则 - 触发路由规则后将加载该微应用 |
||||||
|
*/ |
||||||
|
import type { RegistrableApp } from 'qiankun'; |
||||||
|
import { ComponentOptions } from '@vue/runtime-core'; |
||||||
|
|
||||||
|
//子应用列表
|
||||||
|
const _apps: RegistrableApp<object>[] = []; |
||||||
|
for (const key in import.meta.env) { |
||||||
|
if (key.includes('VITE_APP_SUB_')) { |
||||||
|
const name = key.split('VITE_APP_SUB_')[1]; |
||||||
|
const obj = { |
||||||
|
name, |
||||||
|
entry: import.meta.env[key], |
||||||
|
container: '#content', |
||||||
|
activeRule: name, |
||||||
|
}; |
||||||
|
_apps.push(obj); |
||||||
|
} |
||||||
|
} |
||||||
|
export const apps = _apps; |
@ -0,0 +1,68 @@ |
|||||||
|
/** |
||||||
|
* qiankun配置 |
||||||
|
*/ |
||||||
|
import { registerMicroApps, setDefaultMountApp, start, runAfterFirstMounted, addGlobalUncaughtErrorHandler } from 'qiankun'; |
||||||
|
import { apps } from './apps'; |
||||||
|
import { getProps, initGlState } from './state'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 重构apps |
||||||
|
*/ |
||||||
|
function filterApps() { |
||||||
|
apps.forEach((item) => { |
||||||
|
//主应用需要传递给微应用的数据。
|
||||||
|
item.props = getProps(); |
||||||
|
//微应用触发的路由规则
|
||||||
|
item.activeRule = genActiveRule('/' + item.activeRule); |
||||||
|
}); |
||||||
|
return apps; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 路由监听 |
||||||
|
* @param {*} routerPrefix 前缀 |
||||||
|
*/ |
||||||
|
function genActiveRule(routerPrefix) { |
||||||
|
return (location) => location.pathname.startsWith(routerPrefix); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 微应用注册 |
||||||
|
*/ |
||||||
|
function registerApps() { |
||||||
|
const _apps = filterApps(); |
||||||
|
registerMicroApps(_apps, { |
||||||
|
beforeLoad: [ |
||||||
|
(loadApp) => Promise.resolve(()=>{ |
||||||
|
console.log('before load', loadApp); |
||||||
|
}), |
||||||
|
], |
||||||
|
beforeMount: [ |
||||||
|
(mountApp) => Promise.resolve(()=>{ |
||||||
|
console.log('before mount', mountApp); |
||||||
|
}), |
||||||
|
], |
||||||
|
afterMount: [ |
||||||
|
(mountApp) => Promise.resolve(()=>{ |
||||||
|
console.log('before mount', mountApp); |
||||||
|
}), |
||||||
|
], |
||||||
|
afterUnmount: [ |
||||||
|
(unloadApp) => Promise.resolve(()=>{ |
||||||
|
console.log('after unload', unloadApp); |
||||||
|
}), |
||||||
|
], |
||||||
|
}); |
||||||
|
// 设置默认子应用,与 genActiveRule中的参数保持一致
|
||||||
|
// setDefaultMountApp();
|
||||||
|
// 第一个微应用 mount 后需要调用的方法,比如开启一些监控或者埋点脚本。
|
||||||
|
runAfterFirstMounted(() => console.log('开启监控')); |
||||||
|
// 添加全局的未捕获异常处理器。
|
||||||
|
addGlobalUncaughtErrorHandler((event) => console.log(event)); |
||||||
|
// 定义全局状态
|
||||||
|
initGlState(); |
||||||
|
//启动qiankun
|
||||||
|
start({}); |
||||||
|
} |
||||||
|
|
||||||
|
export default registerApps; |
@ -0,0 +1,39 @@ |
|||||||
|
/** |
||||||
|
*公共数据 |
||||||
|
*/ |
||||||
|
import { initGlobalState, RegistrableApp } from 'qiankun'; |
||||||
|
import { store } from '/@/store'; |
||||||
|
import { router } from '/@/router'; |
||||||
|
import { getAccessToken } from '/@/utils/auth'; |
||||||
|
|
||||||
|
//定义传入子应用的数据
|
||||||
|
export function getProps(){ |
||||||
|
return { |
||||||
|
data: { |
||||||
|
publicPath: '/', |
||||||
|
token: getAccessToken(), |
||||||
|
store, |
||||||
|
router, |
||||||
|
}, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 定义全局状态,并返回通信方法,在主应用使用,微应用通过 props 获取通信方法。 |
||||||
|
* @param state 主应用穿的公共数据 |
||||||
|
*/ |
||||||
|
export function initGlState(info = { userName: 'admin' }) { |
||||||
|
// 初始化state
|
||||||
|
const actions = initGlobalState(info); |
||||||
|
// 设置新的值
|
||||||
|
actions.setGlobalState(info); |
||||||
|
// 注册 观察者 函数 - 响应 globalState 变化,在 globalState 发生改变时触发该 观察者 函数。
|
||||||
|
actions.onGlobalStateChange((newState, prev) => { |
||||||
|
// state: 变更后的状态; prev 变更前的状态
|
||||||
|
console.info('newState', newState); |
||||||
|
console.info('prev', prev); |
||||||
|
for (const key in newState) { |
||||||
|
console.info('onGlobalStateChange', key); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
Loading…
Reference in new issue