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,并通过RegistrableApp的props传给子应用

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,并通过RegistrableApp的props传给子应用(类似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上的onGlobalStateChange和setGlobalState

  • 子应用上新增的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实现应用间通信应该是最好的方式。

相关推荐
子兮曰5 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰5 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万5 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝5 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋5 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁5 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95276 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大6 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师6 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学6 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端