乾坤微服务-主服务读取子服务模板的使用

原创
04/23 15:32
阅读数 112

主服务中审批页加载子服务中的模板展示内容

主服务  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'
  }
}

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部