qiankun实现应用间通信

主应用vue3 + vite

子应用1: Vue3 + vite github.com/huzhushan/v...

子应用2: Create React App + Webpack

通过vuex/pinia实现通信

第一步:在主应用中创建一个store

src/store/index.ts

js 复制代码
const personModule = {
  state: {
    id: 0,
    name: '',
    age: 0
  },
  mutations: {
    setId(state: Object, id: number) {
      state.id = id
    },
    setName(state: Object, name: string) {
      state.name = name
    },
    setAge(state: Object, age: number) {
      state.age = age
    }
  },
  actions: {
    setId(context: Object, id: number) {
      context.commit('setId', id)
    },
    setName(context: Object, name: string) {
      context.commit('setName', name)
    },
    setAge(context: Object, age: number) {
      context.commit('setAge', age)
    }
  }
}

export default new Vuex.Store({
  state: {
    
  },
  getters: {},
  mutations: {

  },
  actions: {

  },
  modules: {
    personModule
  }
})

第二步:在main.js文件中引入这个store,并通过RegistrableAppprops传给子应用

js 复制代码
import store from './store/index'
import { registerMicroApps, start, initGlobalState } from 'qiankun'

registerMicroApps([
  {
    name: 'vue3-element-admin',
    entry: '//localhost:3001',
    container: '#container',
    activeRule: '/#/vue3-element-admin',
    props: {
      store,
    }
  }
],
)

第三步:在子应用的main.js文件中接收这个store,并通过createApp()的第二个参数props,将主应用的这个store传递到子应用的根组件App.vue中。

js 复制代码
renderWithQiankun({
    mount(props) {
      appMount(props);
    },
    //、、、
})

function appMount(props) {
  app = createApp(App, {
    parentStore: props.store
  })
}

第四步:在子应用的根组件App.vue文件中,通过props接收这个store,并通过provite()将这个store注入到所有子组件中

js 复制代码
export default defineComponent({
  props: {
    parentStore: Object
  },
  setup(props) {
    const { lang } = useLang()
    provide('parentStore', props.parentStore)
    //、、、
  }
 })

第五步:在需要的子组件中,通过inject()接收这个store,并根据需要操作这个store

js 复制代码
<script setup>
  import { onMounted, onUnmounted , onActivated, onDeactivated, inject }   from 'vue';
  const parentStore = inject('parentStore')
  const personModule = parentStore.state.personModule
  const changeParentStore = () => {
    parentStore?.dispatch('setId', '11')
    parentStore?.dispatch('setName', 'lily')
    parentStore?.dispatch('setAge', 18)
  }
 </script>

通过vuex创建的store也可以在react子应用中使用

子项目Create-React-App + webpack

第一步,在入口处接收store, 然后传递给根组件

js 复制代码
let root;
function render(props) {
  const rootProps = {
    parentStore: props.store
  }
  root = ReactDOM.createRoot(props?.container ? props.container.querySelector('#root') : document.querySelector('#root'));
  root.render(
    <React.StrictMode>
      <App { ...rootProps  } /> //将store传递给根组件
    </React.StrictMode>
  );
}

export async function mount(props) {
  render(props)
}

第二步:在根组件或其他子组件中使用store

js 复制代码
function App(props) {
  const parentStore = props?.parentStore
  const personModule = props?.parentStore?.state?.personModule
  const changeParentStore = () => {
    parentStore.commit('setId', 11)
    parentStore.commit('setName', 'Lucy')
    parentStore.commit('setAge', 18)
    forceRemount()
  }

  const [key, setKey] = useState(0);
  // 当需要强制重新渲染时,调用这个函数
  const forceRemount = () => {
    setKey(currentKey => currentKey + 1);
  };
  return (
    <div>
      <div>展示主应用vue传过来的store:{personModule?.id}</div>
      <div>展示主应用vue传过来的store:{personModule?.name}</div>
      <div>展示主应用vue传过来的store:{personModule?.age}</div>
      <div>
          <Button type='primary' onClick={changeParentStore}>
            修改主应用的store
          </Button>
      </div>
  </div>
  )

通过EventBus实现通信

第一步:在主应用中创建一个EventBus

src/eventBus/index.ts

js 复制代码
import mitt from 'mitt'
const eventBus = mitt()
export default eventBus;

第二步:在main.js文件中引入这个eventBus,并通过RegistrableAppprops传给子应用(类似Vuex

js 复制代码
import eventBus from './eventBus/index'

registerMicroApps([
  {
    name: 'vue3-element-admin',
    entry: '//localhost:3001',
    container: '#container',
    activeRule: '/#/vue3-element-admin',
    props: {
      store,
      eventBus
    }
  }
],
)

第三步:在子应用的main.js文件中接收这个store,并通过createApp()的第二个参数props,将主应用的这个eventBus传递到子应用的根组件App.vue中。

js 复制代码
renderWithQiankun({
    mount(props) {
      appMount(props);
    },
  })
  
let app;
function appMount(props) {
  app = createApp(App, {
    parentStore: props?.store,
    parentEventBus: props?.eventBus
  })
  //...
}

第四步:在子应用的根组件App.vue文件中,通过props接收这个eventBus,并通过provite()将这个eventBus注入到所有子组件中

js 复制代码
setup(props) {
    provide('parentEventBus', props.parentEventBus)
}

第五步:在主应用的App.vue文件中,引入eventBus,订阅一个setUserName事件

js 复制代码
import eventBus from "./eventBus/index"

const userName : any = ref('')
eventBus.on('setUserName', (name) => {
  userName.value = name;
})

第六步:在子应用需要的子组件中,触发setUserName事件

js 复制代码
const userName = ref('')
  const parentEventBus = inject('parentEventBus')
  const changeUserName = () => {
    parentEventBus?.emit('setUserName', userName.value)
  }

注意:如果订阅事件的组件销毁了,则通信失败

使用 qiankun initGlobalState

第一步: 在主应用中创建一个全局状态

actions.setGlobalState()传入的对象,与原对象存在相同的key则修改value,原对象不存在相同的key则直接新增。

  • 微应用中只能修改已存在的一级属性
js 复制代码
import { registerMicroApps, start, initGlobalState } from 'qiankun'

const state = {
  a: 2,
  b: 2
}
const actions : MicroAppStateActions = initGlobalState(state);
actions.onGlobalStateChange((state, prev) => {
  console.log('主应用监听GlobalState:', state, prev)
})
actions.setGlobalState({
  c: 3, // 该属性会附加到state中
});

第二步:子应用直接使用props上的onGlobalStateChangesetGlobalState

  • 子应用上新增的key不生效
js 复制代码
props.onGlobalStateChange((state, prev) => {
    // state: 变更后的状态; prev 变更前的状态
    console.log('子应用监听GlobalState:', state, prev);
  });

  props.setGlobalState({
    a: 11
  })

  props.setGlobalState({
    b: 22
  })

  props.setGlobalState({
    d: 4, // 新增的id,不会加到state上。
  });
  
  props.setGlobalState({
    c: 33,
  });

综上所述,个人觉得使用Vuex/pinia实现应用间通信应该是最好的方式。

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax