主服务中审批页加载子服务中的模板展示内容
主服务 audit/index.vue页面
// 加载子服务,注册子服务组件回调使用
loadChildApp(appName, ctrlName) {
if (!appName && !ctrlName) {
return
}
const ctrlNamePath = ctrlName.startsWith(appName) ? ctrlName : (appName + '-' + ctrlName)
const appNamePath = appName.startsWith('/') ? appName : '/' + appName
console.log(appNamePath, ctrlNamePath, '=ctrlName=', store.getters.childCtrls)
// 如果缓存存在ctrlName,说明已经注册过了
const item = store.getters.childCtrls.find(v => v.appName === appName && v.name === ctrlName)
if (item) {
console.log('子应用组件已注册', item)
this.isShow = false
this.compName = item.component.default
this.$nextTick(() => {
this.isShow = true // 查看模板与编辑模板是一个时这里强制重新渲染
})
return
}
// 构建路由参数对象,模拟路径跳转,复用加载子应用逻辑
const to = { path: appNamePath }
const callback = () => {
console.log('子应用加载完成 回调组件存入childCtrls=', store.getters.childCtrls)
// 子应用加载完成之后应该已经将组件注册完毕,此时如果仍找不到,说明子应用未注册
const item = store.getters.childCtrls.find(v => v.appName === appName && v.name === ctrlName)
console.log(item, 'item===', appName, ctrlName)
if (item) {
this.isShow = false
this.compName = item.component.default
this.$nextTick(() => {
this.isShow = true // 查看模板与编辑模板是一个时这里强制重新渲染
})
} else {
this.$message.error('子应用组件未注册')
}
}
store.dispatch('app/loadChildApp', { to, menu: store.getters.menu, callback })
},
主服务store中加载乾坤微服务部分
src\store\modules\app.js
import { loadMicroApp } from 'qiankun'
import { getMicrosApp } from '@/api/login'
const state = {
// 子项目app配置信息
microApps: {}, // 微应用 实例
childApps: [],
childCtrls: []
}
const mutations = {
SET_CHILD_CTRLS: (state, ctrls) => {
state.childCtrls = state.childCtrls.concat(ctrls)
},
SET_CHILD_APP: (state, childApp) => {
state.childApps = childApp
},
SET_CHILD_APP_LOADED: (state, index) => {
state.childApps[index].loaded = true
}
}
const actions = {
setChildApp({ commit }) {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async resolve => {
const { data } = await getMicrosApp() //获取所有子服务列表接口
const apps = data.records.map(item => {
return {
config: {
name: item.microApplicationName,
entry: process.env.NODE_ENV === 'development' ? item.microApplicationDevAddress : item.microApplicationAddress,
container: '#' + item.parentApplicationTemplate,
microApplicationHost: item.microApplicationHost
},
loaded: false,
routeStartPath: item.routingRules
}
})
commit('SET_CHILD_APP', apps)
resolve()
})
},
loadChildApp({ commit, state }, info) {
return new Promise(resolve => {
let isLoad = false
const path = info.to.path
state.childApps.some((ele, index) => {
if (path.startsWith(ele.routeStartPath)) {
if (!ele.loaded) {
isLoad = true
const routePath = ele.routeStartPath
const menuRoute = []
checkChildPathToRouter(routePath, info.menu, menuRoute)
dealHussarRoute(menuRoute)
// 微应用缓存问题
ele.config.entry += `?hash=${new Date().getTime()}`
state.microApps[ele.routeStartPath] = loadMicroApp({
...ele.config,
props: {
menuRoute,
componentsModules,
request,
utils,
filters,
requestHeaders: appVersion.getAjaxHeaders(),
callback: components => {
console.log(components, 'components===')
commit('SET_CHILD_CTRLS', components) // 这里把子服务回调的组件存起来
info.callback && info.callback()
console.log('callback:', moment(new Date()).format('YYYY-MM-DD HH:mm:ss'), ele.routeStartPath)
}
}
}, {
sandbox: {
// strictStyleIsolation: true,
experimentalStyleIsolation: ele.routeStartPath.includes('lowcode')
}
})
console.log('微应用加载中...', ele.routeStartPath)
state.microApps[ele.routeStartPath].loadPromise.then(() => {
resolve()
commit('SET_CHILD_APP_LOADED', index)
}).catch(() => {
console.warn('微应用加载失败')
window.vm.$message.error('系统正在维护,请联系管理员')
})
}
return true
}
})
if (!isLoad) {
resolve()
}
})
}
}
export default {
state,
mutations,
actions
}
子服务中main.js中将子服务审批页组件模板回调
子服务 main.js 页面
const config = require('./config.js') //读取的组件配置
/**
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount(props: any) {
render(props)
}
// props参数是主服务发送过来的
async function render(props?: any) {
// 传递请求axios封装
appProps = props
if (props && props.request) {
Vue.prototype.$util = props.request
}
//将主服务的公共组件注册到子服务中使用
const busiCom = (props && props.componentsModules) || [];
[...busiCom, ...componentsModules].map((module: any) => {
const name = module.default.componentName
name && Vue.component(name, module.default)
})
// 将主服务的公共函数注册到子服务中使用
if (props && props.utils) {
Vue.prototype.$utils = { ...props.utils, ...utils }
}
// 将主服务的公共过滤器注册到子服务中使用
if (props && props.filters) {
Object.keys(props.filters).forEach(key => {
Vue.filter(key, props.filters[key])
})
}
// 将主服务的公共指令注册到子服务中使用
if (props && props.directives) {
Vue.use(props.directives)
}
// 子应用组件向父应用注册回调
if (props && props.callback && config.ideaComponent) {
props.callback(Object.keys(config.ideaComponent).map(key => {
return {
name: key,
appName: config.microAppName,
component: require('@/views/' + config.ideaComponent[key])
}
}))
}
// 将主服务的全局监听注册到子服务中使用
if (props && props.Observer) {
Vue.use(props.Observer)
}
// 配置路由
if (props && props.menuRoute) {
Vue.use(VueRouter)
const routes = props.menuRoute.map((item: any) => {
return {
...item,
component: (resolve: any) => require(['@/views/' + item.routeUrl], resolve)
}
})
// 添加静态路由
routes.push(...staticRoutes)
const router = new VueRouter({
routes
})
vm = new Vue({
router,
store,
render: h => h(App)
}).$mount(`#${config.microAppName}-web-child`)
}
}
子服务中要导出的组件模板
src/config.js
module.exports = {
// 名称需要与微应用名称保持一致
microAppName: 'performance-app',
appName: 'performance-app',
// 向父应用注册的组件: 组件地址为views下相对路径
ideaComponent: {
'project-apply': 'projectInput/process/index.vue'
}
}