前言
上篇主要记录了如果使用 qiankun,本文记录下 qiankun 应用间如何通信。
一、如何划分子应用
在微前端架构中,我们应该按业务划分出对应的子应用,而不是通过功能模块划分子应用。主要原因为:
- 在微前端架构中,子应用并不是一个模块,而是一个独立的应用,我们将子应用按业务划分可以拥有更好的可维护性和解耦性。
- 子应用应该具备独立运行的能力,应用间频繁的通信会增加应用的复杂度和耦合度。?
二、Actions 通信
这是官方提供的应用间的通信方式 - Actions 通信,这种通信方式比较适合业务划分清晰,应用间通信较少的微前端应用场景。
通信原理
qiankun 内部提供了 initGlobalState 方法用于注册 MicroAppStateActions 实例用于通信,该实例有三个方法,分别是:
- setGlobalState:设置 globalState。设置新的值时,内部将执行浅检查,如果检查到 globalState 发生改变则触发通知,通知到所有的观察者函数。
- onGlobalStateChange:注册观察者函数。响应 globalState 变化,在 globalState 发生改变时触发该观察者函数。
- offGlobalStateChange:取消观察者函数。该实例不再响应 globalState 变化。
三、主应用的工作
1、首先,在主应用中注册一个 MicroAppStateActions 实例并导出。
在 main-app 项目中,新建文件 main-app/src/micros/actions.js。
// main-app/src/micros/actions.js
import { initGlobalState } from 'qiankun'
// 初始化 state
const initState = {
name: 'main-app',
msg: '主应用消息'
}
const actions = initGlobalState(initState)
export default actions
2、在注册??MicroAppStateActions 实例后,在需要通信的组件中使用该实例,并注册观察者函数。
<!-- main-app/src/components/HelloWorld.vue -->
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<button @click="handleActions">主应用通信按钮</button>
</div>
</template>
<script>
import actions from '@/micros/actions'
export default {
name: 'HelloWorld',
props: {
msg: String
},
mounted() {
// 注册一个观察者函数
// state 是变更后的状态,prevState 是变更前的状态
actions.onGlobalStateChange((state, prevState) => {
console.log("主应用观察者,改变前的值", prevState)
console.log("主应用观察者,改变后的值", state)
})
},
methods: {
handleActions() {
actions.setGlobalState({
msg: `主应用消息msg,${Math.random()}`
})
}
}
}
</script>
<style scoped lang="less">
</style>
点击主应用页面按钮,触发如下图:
四、子应用的工作
1、进入子应用的配置,首先设置一个 Actions 实例。新增文件 vue2-app/src/micros/actions.js。
function emptyAction() {
// 警告:提示当前使用的是空 Action
console.warn('Current execute action is empty!')
}
class Actions {
// 默认值为空 Action
actions = {
onGlobalStateChange: emptyAction,
setGlobalState: emptyAction,
}
/**
* 设置 actions
*/
setActions(actions) {
this.actions = actions
}
/**
* 映射
*/
onGlobalStateChange(...args) {
return this.actions.onGlobalStateChange(...args)
}
/**
* 映射
*/
setGlobalState(...args) {
return this.actions.setGlobalState(...args)
}
}
const actions = new Actions()
export default actions
2、创建 actions 实例后,需要为其注入真是 Actions。在入口文件 main.js 的 render 函数中注入。
// 部分代码
import actions from '@/micros/actions.js'
Vue.config.productionTip = false
// 定义一个Vue实例
let instance = null
// 渲染方法
function render(props = {}) {
if(props) actions.setActions(props)
const { container } = props
instance = new Vue({
router,
render: (h) => h(App)
}).$mount(container ? container.querySelector('#app'): '#app')
}
3、页面中使用
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>qiankun 主应用带过来的消息:{{microInfo}}</p>
<button @click="handleActions">子应用按钮</button>
</div>
</template>
<script>
import actions from '@/micros/actions.js'
export default {
name: 'HelloWorld',
data () {
return {
msg: 'VUE2-APP 子应用',
microInfo: {}
}
},
mounted() {
// 注册观察者函数
actions.onGlobalStateChange(state => {
console.log('子应用的观察函数:', state)
this.microInfo = state
}, true)
},
methods: {
handleActions() {
actions.setGlobalState({
msg: `子应用传递过来消息,${Math.random()}`
})
}
},
}
</script>
<style scoped>
</style>
页面展示效果如下图。
?至此,主应用与子应用之间的基本通信就建立了。
|