vue中qiankun架子,基站与微服务之间的通讯方式

vue中使用qiankun,基站与微服务之间的通讯方式

1、第一种根据官方体统的action方式
基站
传:actions.setGlobalState
收:actions.onGlobalStateChange

import {
  registerMicroApps,
  addGlobalUncaughtErrorHandler,
  start,
  initGlobalState
} from 'qiankun' // 微应用注册信息
import apps from './app'

registerMicroApps(apps, {
  beforeLoad: (app) => {
    console.log('before load', app.name);
    return Promise.resolve();
  },
  afterMount: (app) => {
    console.log('after mount', app.name);
    return Promise.resolve();
  },
});

addGlobalUncaughtErrorHandler((event) => {
  console.error(event);
  const { message: msg } = event
  if (msg && msg.includes('died in status LOADING_SOURCE_CODE')) {
    console.error('微应用加载失败,请检查应用是否可运行')
  }
});
const state = {}
const actions = initGlobalState(state)
//传参,在需要传递参数的地方直接调用
actions.setGlobalState({ path: '/resourcesCore/colonyManage', token: 121 })
//接收
actions.onGlobalStateChange((state, prev) => {
  // state: 变更后的状态; prev 变更前的状态
  console.log('基站',state, prev);
});

export { actions }
export default start

微服务,
传:props.setGlobalState
收:props.onGlobalStateChange

/*
 * @Author: your name
 * @Date: 2021-10-11 18:53:39
 * @LastEditTime: 2021-11-07 22:59:43
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /pm-ui/src/main.js
 */

import Vue from 'vue'

import Cookies from 'js-cookie'

import 'normalize.css/normalize.css' // a modern alternative to CSS resets
import Element from 'element-ui'
import './styles/element-variables.scss'
// import enLang from 'element-ui/lib/locale/lang/en'// 如果使用中文语言包请默认支持,无需额外引入,请删除该依赖

import '@/styles/index.scss' // global css

import App from './App'
import store from './store'
import router from './router'

import './icons' // icon
import './permission' // permission control
import './utils/error-log' // error log
// 清空表单
import resetForm from '../src/utils/resrtForm'
Vue.prototype.$resetForm = resetForm

// 数据的快速复制
import objCoppy from '../src/utils/objCoppy'
Vue.prototype.$objCoppy = objCoppy

// 信息提示框
import myconfirm from '../src/utils/myconfirm'
Vue.prototype.$myconfirm = myconfirm

import * as filters from './filters' // global filters

// 按钮权限判断
import hasPermission from '@/permission/index'
Vue.prototype.hasPerm = hasPermission

import httpRspCode from '@/utils/rspCode'
Vue.prototype.httpRspCode = httpRspCode

// 组件通讯工具
Vue.prototype.$EventBus = new Vue()

/**
 * If you don't want to use mock-server
 * you want to use MockJs for mock api
 * you can execute: mockXHR()
 *
 * Currently MockJs will be used in the production environment,
 * please remove it before going online ! ! !
 */
// if (process.env.NODE_ENV === 'production') {
//   const { mockXHR } = require('../mock')
//   mockXHR()
// }

// 自定义组件
import MyComponents from '@/components'
Vue.use(MyComponents)

Vue.use(Element, {
  size: Cookies.get('size') || 'medium' // set element-ui default size
  // locale: enLang // 如果使用中文,无需设置,请删除
})

// register global utility filters
Object.keys(filters).forEach(key => {
  Vue.filter(key, filters[key])
})

Vue.config.productionTip = false

// 新增:用于保存vue实例
let instance = null;

// 新增:动态设置 webpack publicPath,防止资源加载出错
if (window.__POWERED_BY_QIANKUN__) {
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
/** * 新增: * 渲染函数 * 两种情况:主应用生命周期钩子中运行 / 微应用单独启动时运行 */
function render(props = {}) {
  console.log(props)
  const { container,onGlobalStateChange } = props;
  if(onGlobalStateChange){
    setTimeout(()=>{
      props.bus.$emit('setBusToken','456')
      props.setGlobalState({ token: 'microActionToken' })
      console.log(123)
    },5000)
    props.onGlobalStateChange((state, prevState) => {
      // state: 变更后的状态; prev 变更前的状态
      state.path ? router.push(state.path) : ''
      console.log('通信状态发生改变:', state, prevState);
      // 这里监听到globalToken变化再更新store
      // store.commit('setToken', '******')
    }, true);
  }
  // 挂载应用
  instance = new Vue({
    router,
    store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#micro-app-child') : '#micro-app-child');
}
/**
 * 新增:
 * bootstrap 只会在微应用初始化的时候调用一次,
 下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
export async function bootstrap() {
  console.log("VueMicroApp bootstraped");
}
/**
 * 新增:
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {
  console.log("VueMicroApp mount22", props);
  setTimeout(()=>{
    props.setGlobalState({ name: '基站' });
  },2000)
  render(props);
}
/**
 * 新增:
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount() {
  console.log("VueMicroApp unmount");
  instance.$destroy();
  instance = null;
}
// 新增:独立运行时,直接挂载应用
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

// new Vue({
//   el: '#app',
//   router,
//   store,
//   render: h => h(App)
// })

第二种:vue的Eventbus
基站,定义eventbus,通过props的方式传入微服务
只看props.bus.$emit就好

import Vue from 'vue'
const bus = new Vue({
  data: {
    // 保持初始化时与store数据一致
    // 基本类型可以这样用,引用类型请用cloneDeep深拷贝
    // https://www.lodashjs.com/docs/lodash.cloneDeep#_clonedeepvalue
    token: 123
  }
})
Vue.prototype.$bus = bus
const apps = [
  {
    name: 'micro-app-order',
    entry: '//localhost:9527',
    container: '#order-container',
    activeRule: '#/resourcesCore',
    props: {
      bus
    }
  }
]
export default apps

微服务入口文件接收并使用,并且可以动态 b u s . bus. bus.emit的方式传递值给基站

/*
 * @Author: your name
 * @Date: 2021-10-11 18:53:39
 * @LastEditTime: 2021-11-07 22:59:43
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /pm-ui/src/main.js
 */

import Vue from 'vue'

import Cookies from 'js-cookie'

import 'normalize.css/normalize.css' // a modern alternative to CSS resets
import Element from 'element-ui'
import './styles/element-variables.scss'
// import enLang from 'element-ui/lib/locale/lang/en'// 如果使用中文语言包请默认支持,无需额外引入,请删除该依赖

import '@/styles/index.scss' // global css

import App from './App'
import store from './store'
import router from './router'

import './icons' // icon
import './permission' // permission control
import './utils/error-log' // error log
// 清空表单
import resetForm from '../src/utils/resrtForm'
Vue.prototype.$resetForm = resetForm

// 数据的快速复制
import objCoppy from '../src/utils/objCoppy'
Vue.prototype.$objCoppy = objCoppy

// 信息提示框
import myconfirm from '../src/utils/myconfirm'
Vue.prototype.$myconfirm = myconfirm

import * as filters from './filters' // global filters

// 按钮权限判断
import hasPermission from '@/permission/index'
Vue.prototype.hasPerm = hasPermission

import httpRspCode from '@/utils/rspCode'
Vue.prototype.httpRspCode = httpRspCode

// 组件通讯工具
Vue.prototype.$EventBus = new Vue()

/**
 * If you don't want to use mock-server
 * you want to use MockJs for mock api
 * you can execute: mockXHR()
 *
 * Currently MockJs will be used in the production environment,
 * please remove it before going online ! ! !
 */
// if (process.env.NODE_ENV === 'production') {
//   const { mockXHR } = require('../mock')
//   mockXHR()
// }

// 自定义组件
import MyComponents from '@/components'
Vue.use(MyComponents)

Vue.use(Element, {
  size: Cookies.get('size') || 'medium' // set element-ui default size
  // locale: enLang // 如果使用中文,无需设置,请删除
})

// register global utility filters
Object.keys(filters).forEach(key => {
  Vue.filter(key, filters[key])
})

Vue.config.productionTip = false

// 新增:用于保存vue实例
let instance = null;

// 新增:动态设置 webpack publicPath,防止资源加载出错
if (window.__POWERED_BY_QIANKUN__) {
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
/** * 新增: * 渲染函数 * 两种情况:主应用生命周期钩子中运行 / 微应用单独启动时运行 */
function render(props = {}) {
  console.log(props)
  const { container,onGlobalStateChange } = props;
  if(onGlobalStateChange){
    setTimeout(()=>{
      props.bus.$emit('setBusToken','456')
      props.setGlobalState({ token: 'microActionToken' })
      console.log(123)
    },5000)
    props.onGlobalStateChange((state, prevState) => {
      // state: 变更后的状态; prev 变更前的状态
      state.path ? router.push(state.path) : ''
      console.log('通信状态发生改变:', state, prevState);
      // 这里监听到globalToken变化再更新store
      // store.commit('setToken', '******')
    }, true);
  }
  // 挂载应用
  instance = new Vue({
    router,
    store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#micro-app-child') : '#micro-app-child');
}
/**
 * 新增:
 * bootstrap 只会在微应用初始化的时候调用一次,
 下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
export async function bootstrap() {
  console.log("VueMicroApp bootstraped");
}
/**
 * 新增:
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {
  console.log("VueMicroApp mount22", props);
  setTimeout(()=>{
    props.setGlobalState({ name: '基站' });
  },2000)
  render(props);
}
/**
 * 新增:
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount() {
  console.log("VueMicroApp unmount");
  instance.$destroy();
  instance = null;
}
// 新增:独立运行时,直接挂载应用
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

// new Vue({
//   el: '#app',
//   router,
//   store,
//   render: h => h(App)
// })

第二种方式的好处是,基站和微服务可以设置同一个store,然后直接替换,微服务想要改变值的时候不需要判断是不是单独启动的,直接改变即可,使用时根据各自的业务场景判断,
如需参考详细的,详细代码可参考:樊小书生的原创文章添加链接描述

你可能感兴趣的:(vue.js,javascript,微服务)