场景描述:子应用需要在接口调用和页面渲染时,需要用到主应用登录之后拿到的用户数据
逻辑前提:
1、主应用在 main.js中通过 registerMicroApps注册了子应用
2、主应用登录之后将用户数据传递给子应用
>> 原先的做法(有问题)
【具体参考 qiankun #initGlobalState】这个数据传递的方法是没有问题的,只是不满足当前的场景
1、主应用在注册子应用时,在子应用的生命周期钩子afterMount方法中通过setGlobalState方法将用户数据传递出去
// main.js
registerMicroApps(
[
{
name: 'custproApp',
entry: '/MicroCustpro/',
container: '#appContainer',
activeRule: 'app-custpro',
},
],
{
afterMount: [(app) => {
// eslint-disable-next-line
console.log(`[base-app]: catch [${app.name}] afterMount`)
qiankunActions.setGlobalState({
userInfo: store.getters.userInfo
})
}],
}
)
2、子应用在导出的生命周期钩子mount方法中通过onGlobalStateChange方法监听主应用的数据传递,从而拿到用户数据
// main.js
export async function mount (props) {
console.log('[app-cust] vue app mounted, props from main framework', props)
render(props)
// 主应用通信
props.onGlobalStateChange((state) => {
const { userInfo = {} } = state
// 用户信息保存
if (userInfo) store.dispatch('initUserInfo', { ...userInfo })
console.log('[app-cust]: catch [base-app] state')
})
}
【问题现象】:主应用登录之后加载子应用,子应用加载之后最初调用的几个接口中并没有带上用户数据,页面渲染出来更早一点的部分也出现没有拿到用户数据的情况
【原因分析】:主应用在子应用 afterMount 加载完之后才传递的数据,子应用 mount 加载之后最初调用的接口,以及靠前一点的部分页面渲染,可能比子应用监测到主应用传递的数据更早发生
>> 修改后的做法
1、主应用在注册子应用时,在props中通过函数的方式返回主应用存储在全局状态 (vuex等)中的用户数据
// main.js
registerMicroApps(
[
{
name: 'custproApp',
entry: '/MicroCustpro/',
container: '#appContainer',
activeRule: 'app-custpro',
props: getUserInfo () => ({ userInfo: store.getters.userInfo })
},
]
)
2、子应用在导出的生命周期钩子mount方法中通过props从主应用的全局状态中取到用户数据
// main.js
export async function mount (props) {
console.log('[app-cust] vue app mounted, props from main framework', props)
if (props.getUserInfo) {
// 用户信息保存
const { userInfo } = props.getUserInfo()
if (userInfo) store.dispatch('initUserInfo', { ...userInfo })
console.log('---user---', userInfo.userName, userInfo.userId)
}
render(props)
}