signal communication
Before introducing the application communication of "qiankun", we need to understand how the micro front-end architecture divides sub applications.
In the micro front-end architecture, we should divide the corresponding sub applications by business, rather than dividing the sub applications by functional modules. There are two reasons for this:
- In the micro front-end architecture, the sub application is not a module, but an independent application. We can have better maintainability and decoupling by dividing the sub application by business.
- Sub applications should have the ability to run independently. Frequent communication between applications will increase the complexity and coupling of applications.
To sum up, we should divide each sub application from the perspective of business to reduce the communication between applications as much as possible, so as to simplify the whole application and make our micro front-end architecture more flexible and controllable.
We will introduce two communication methods in this tutorial,
- The first is action communication, an official communication method provided by qiankun. It is suitable for micro front-end applications with clear business division and relatively simple. Generally speaking, the first scheme can meet the needs of most application scenarios.
- The second is Storage communication, which is based on local Storage and sessionStorage. It is suitable for tracking the communication status, such as login information and token. The sub application has the ability to run independently.
- The third method is based on props, which is used to transfer values from the main application to the sub application. It is applicable to shared components of main and sub applications, public method calls, etc.
Actions communication
Let's first introduce the official inter application communication mode - Actions communication. This communication mode is more suitable for micro front-end application scenarios with clear business division and less inter application communication.
Communication principle
The "initGlobalState" method provided by qiankun is used to register the "MicroAppStateActions" instance for communication. The instance has three methods, namely:
- setGlobalState: set global state - when setting a new value, a shallow check will be performed internally. If it is detected that the global state has changed, a notification will be triggered to notify all observers of the global state function.
- onGlobalStateChange: register the {observer} function - respond to the change of} global state and trigger the} observer function when the} global state changes.
- offGlobalStateChange: cancels the "Observer" function - the instance no longer responds to "globalState" changes.
Let's draw a picture to help you understand (see the figure below)
As can be seen from the above figure, we can register "Observer" into the observer pool first, and then modify "globalState" to trigger all "Observer" functions, so as to achieve the effect of communication between components.
Api
Understanding: the global state here is very similar to the state in vuex, except that the global state can be shared in the main application and micro application
Simple experiment
Main application
New SRC - > actions js
import { initGlobalState } from 'qiankun'; import store from './store'; const initialState = { //Write initialization data here }; // Initialize state const actions = initGlobalState(initialState); actions.onGlobalStateChange((state, prev) => { //Monitor changes in public status console.log('Main application: Before change'); console.log(prev); console.log('Main application: After change'); console.log(state); store.commit('setProject', state); //Here I save the public state in the vuex of the main application }); export default actions;
Using actions in components
tab.vue
<template> <div> <button @click="sendMes1"> Click send message 1 to sub application</button> <button @click="sendMes2"> Click send message to subapplication 2</button> <p> Currently displayed items:{{project}} </p> </div> </template> <script> import actions from './actions'//Remember to import the actions instance export default { data() { return { mes1: { project_id: 'Item 1' }, mes2: { project_id: 'Item 2' }, } }, computed: { project: function () { return this.$store.state.project_id } }, methods: { sendMes1() { actions.setGlobalState(this.mes1);//Changing the global state through setGlobalState }, sendMes2() { actions.setGlobalState(this.mes2); } }, } </script>
Micro application
New SRC - > actions js
function emptyAction() { //Set an actions instance // Prompt: empty Action is currently used console.warn('Current execute action is empty!'); } class Actions { // The default value is empty Action actions = { onGlobalStateChange: emptyAction, setGlobalState: emptyAction, }; /** * Set actions */ setActions(actions) { this.actions = actions; } /** * mapping */ onGlobalStateChange(...args) { return; this.actions.onGlobalStateChange(...args); } /** * mapping */ setGlobalState(...args) { return; this.actions.setGlobalState(...args); } } const actions = new Actions(); export default actions;
main.js
Inject the actions instance into the mounted lifecycle
export async function mount(props) { actions.setActions(props); //Inject actions instance render(props); }
Use in vue components
1.vue
<template> <div> <div> This is a sub application </div> <p>Received message:{{mes}}</p> <button @click="butClick">Click send message to parent app</button> </div> </template> <script> import actions from '../actions'//Import instance export default { data() { return { mes: '', } }, mounted() { actions.onGlobalStateChange((state) => { //Listen for global status this.mes = state }, true); }, methods: { butClick() { actions .setGlobalState({ project_id: 'Item 99' })//Change global state } } } </script>
Storage communication
Communication principle
storage Namespace,See for detailsportal/src/utils/storageNameSpace.js
- Stored value in main application sesstionstorage setItem('a', 'b', true)
/ / the "main application: a" will be automatically added to the key as the key
Value sesstionstorage getItem('a', true)
Clear the value sessionstorage removeItem('a', true)
Empty
sessionStorage.clear(true) / / clear all sessionstorage, including sub applications
sessionStorage.clear('self ') / / clear the sessionstorage of the main application
- Sub application
Stored value sessionstorage setItem('a', 'b')
// 'Application Name: a' will be automatically added to the key as the key
Value sessionstorage getItem('a')
Clear the value sessionstorage removeItem('a')
Empty sessionstorage clear()
//Only clear the sessionStorage of the current application and obtain the sessionStorage of other sub applications
sessionStorage. Getitem (sub application name: + key)
localStorage AndsessionStorageequally
props communication
In the micro front-end applications built above, the communication between father and son is an extremely common and unavoidable demand, and qiankun certainly has consideration in this regard.
Parent application
In the main application portal / SRC / singlespa When registering a sub application in JS, pass the defined msg to the sub application through the props parameter.
// Define the data passed into the sub application const msg = { data: { auth: false }, fns: { portal_alert(txt) { // txt value passed by subapplication alert('Method of parent application:' + txt) }, portal_logout() { parentThat.$store.dispatch('fedLogOut').then(() => { const fullPath = parentThat.$route.fullPath const path = fullPath ? `/portal-login?redirect=${fullPath}` : '/portal-login' parentThat.$router.push({ path }) location.reload() // To re instantiate the Vue router object and avoid bug s }) } } // Register subapplications registerMicroApps([ { name: 'app1', entry: '//localhost:7771', render, activeRule: genActiveRule('/app1'), props: msg, // Pass the defined data to the sub application }, ])
Sub application
In the sub application's main In the bootstrap function of JS, hang the functions in the received props parameters on the vue prototype for easy use. You can also get props in other exported life cycle functions and handle them according to your imagination.
export async function bootstrap (props = {}) { // console.log('sub-app1 loading ') / / the value passed by the parent application is mounted on the vue prototype Vue.prototype.parentData = {...props.data} / / mount the method passed by the parent application on the prototype Vue.prototype.parentFns = props.fns } |