qiankun 子应用怎样通过 props拿到子应用【注册之后挂载之前】主应用中发生变更的数据

发布于:2025-05-31 ⋅ 阅读:(33) ⋅ 点赞:(0)

场景描述:子应用需要在接口调用和页面渲染时,需要用到主应用登录之后拿到的用户数据
逻辑前提:
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)
}