通信原理:
qiankun框架提供了一个全局对象initGlobalState,可以用来存储全局共享的数据。各个子应用可以通过initGlobalState读取和修改数据,initGlobalState会返回三个方法,分别是:
- setGlobalState:设置 globalState - 设置新的值时,内部将执行 浅检查,如果检查到 globalState 发生改变则触发通知,通知到所有的 观察者 函数。
- onGlobalStateChange:注册 观察者 函数 - 响应 globalState 变化,在 globalState 发生改变时触发该 观察者 函数。
- offGlobalStateChange:取消 观察者 函数 - 该实例不再响应 globalState 变化。
官方示例:
主应用:
import { initGlobalState, MicroAppStateActions } from 'qiankun';
// 初始化 state
const actions: MicroAppStateActions = initGlobalState(state);
actions.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
actions.setGlobalState(state);
actions.offGlobalStateChange();
微应用:
// 从生命周期 mount 中获取通信方法,使用方式和 master 一致
export function mount(props) {
props.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
props.setGlobalState(state);
}
封装:
主应用 注册 MicroAppStateActions 实例,将这个actions通过props穿给微应用
import { initGlobalState } from 'qiankun';
// 父应用的初始state
const initialState = {
user: {
name: '张三',
},
};
const actions = initGlobalState(initialState);
actions.onGlobalStateChange((newState, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log('main change', JSON.stringify(newState), JSON.stringify(prev));
for (const key in newState) {
initialState[key] = newState[key];
}
});
// 定义一个获取state的方法下发到子应用
actions.getGlobalState = key => {
// 有key,表示取globalState下的某个子级对象
// 无key,表示取全部
return key ? initialState[key] : initialState;
};
export default actions;
微应用 中接收参数,并将它注册到vuex里面
/**
*
* @param {vuex实例} store
* @param {qiankun下发的props} props
*/
function registerGlobalModule (store, props = {}) {
if (!store || !store.hasModule) {
return;
}
// 获取初始化的state
const initState = props.getGlobalState && props.getGlobalState() || {
user: {}
};
// 将父应用的数据存储到子应用中,命名空间固定为global
if (!store.hasModule('global')) {
const globalModule = {
namespaced: true,
state: initState,
actions: {
// 子应用改变state并通知父应用
setGlobalState ({ commit }, payload) {
commit('setGlobalState', payload);
},
// 初始化,只用于mount时同步父应用的数据
initGlobalState ({ commit }, payload) {
commit('setGlobalState', payload);
},
},
mutations: {
setGlobalState (state, payload) {
// eslint-disable-next-line
state = Object.assign(state, payload);
// 通知父应用
if (props.setGlobalState) {
props.setGlobalState(state);
}
},
},
};
store.registerModule('global', globalModule);
} else {
// 每次mount时,都同步一次父应用数据
store.dispatch('global/initGlobalState', initState);
}
};
export default registerGlobalModule;
在微应用mount钩子中调用
export async function mount (props) {
console.log('[vue] props from main framework', props)
registerGlobalModule.globalRegister(store, props)
render(props)
}