前面讲到了微前端的应用:(94条消息) 微前端应用(qiankun+umi+antd)_他夏了夏天吖的博客-CSDN博客 https://blog.csdn.net/zh0623/article/details/130615234?spm=1001.2014.3001.5501今天讲一下不同子应用的通信和数据共享问题
https://blog.csdn.net/zh0623/article/details/130615234?spm=1001.2014.3001.5501今天讲一下不同子应用的通信和数据共享问题
微前端不同子应用之间可能需要进行通信和数据共享,假如子应用分别为react.js项目和vue.js项目。不同子应用要跨应用通信方案,可以使用自定义事件、消息总线或共享状态库等
1.自定义事件
自定义事件是一种简单的跨应用通信方案,它允许不同的子应用之间通过事件来进行通信。在React和Vue中,我们可以使用自定义事件来实现跨组件通信。下面是一个简单的例子:
在React中:
import React, { useState } from 'react';
function App() {
  const [count, setCount] = useState(0);
  function handleClick() {
    window.dispatchEvent(new CustomEvent('increment', { detail: { count: count + 1 } }));
  }
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increment</button>
    </div>
  );
}
export default App;在Vue中:
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="handleClick">Increment</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    handleClick() {
      window.dispatchEvent(new CustomEvent('increment', { detail: { count: this.count + 1 } }));
    },
  },
};
</script>在上面的例子中,我们在React和Vue中都使用了自定义事件来实现跨组件通信。当用户点击“Increment”按钮时,我们会触发一个名为“increment”的自定义事件,并将当前计数器的值作为事件的详细信息传递给其他子应用。
2. 消息总线
消息总线是一种更高级的跨应用通信方案,它允许不同的子应用之间通过消息队列来进行通信。在React和Vue中,我们可以使用第三方库(如PubSubJS)来实现消息总线。下面是一个简单的例子:在React中:
import React, { useState, useEffect } from 'react';
import PubSub from 'pubsub-js';
function App() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    const token = PubSub.subscribe('increment', (msg, data) => {
      setCount(data.count);
    });
    return () => {
      PubSub.unsubscribe(token);
    };
  }, []);
  function handleClick() {
    PubSub.publish('increment', { count: count + 1 });
  }
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increment</button>
    </div>
  );
}
export default App;在Vue中:
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="handleClick">Increment</button>
  </div>
</template>
<script>
import PubSub from 'pubsub-js';
export default {
  data() {
    return {
      count: 0,
    };
  },
  mounted() {
    PubSub.subscribe('increment', (msg, data) => {
      this.count = data.count;
    });
  },
  methods: {
    handleClick() {
      PubSub.publish('increment', { count: this.count + 1 });
    },
  },
};
</script>在上面的例子中,我们在React和Vue中都使用了PubSubJS库来实现消息总线。当用户点击“Increment”按钮时,我们会发布一个名为“increment”的消息,并将当前计数器的值作为消息的详细信息传递给其他子应用。同时,我们还在组件中订阅了“increment”消息,并在收到消息时更新计数器的值。
除了上面的方式,消息总线还有以下几种方式:
1. 本地事件总线:使用事件监听和事件触发在同一个应用内部通信。
 2. 跨窗口消息传递:使用 postMessage 在不同的浏览器窗口/标签页之间通信。
 3. Web Sockets:使用 WebSocket 协议在客户端和服务器之间建立持久连接,进行双向通信。
 4. 本地存储事件:使用本地存储监听 storage 事件在不同的浏览器窗口/标签页之间通信。
 5. 第三方消息代理:使用第三方服务如 Pusher、Socket.io 等在客户端之间传递消息。
2.1 本地事件总线
React 项目:
js
// React 项目
import { useState } from 'react';
// 创建事件总线
const eventBus = {
  on(event, callback) {
    document.addEventListener(event, callback);
  },
  emit(event, data) {
    document.dispatchEvent(new CustomEvent(event, { detail: data })); 
  } 
}
function ReactApp() {
  const [msg, setMsg] = useState('');
  
  // 监听事件
  useEffect(() => {
    eventBus.on('message', (e) => {
      setMsg(e.detail); 
    })
  }, []);
  
  return <div>{msg}</div>  
}
Vue项目:
js
// Vue 项目
// 创建事件总线
const eventBus = new Vue(); 
methods: {
  sendMessage() {
    eventBus.$emit('message', 'Hello from Vue!'); 
  }
},
mounted() {
  eventBus.$on('message', (msg) => {
    this.msg = msg; 
  });
}2.2 跨窗口消息传递postMessage
//React:
js
// 发送消息
window.opener.postMessage('Hello from React!', '*');
// 接收消息
window.addEventListener('message', (e) => {
  console.log(e.data); // Hello from Vue!
});
//Vue:
js
// 发送消息
window.opener.postMessage('Hello from Vue!', '*');
// 接收消息
window.addEventListener('message', (e) => {
  console.log(e.data); // Hello from React!
});3. Web Sockets进行双向通信
js
// React 项目
import { useState, useEffect } from 'react';
function ReactApp() {
  const [msg, setMsg] = useState('');
  
  // 连接 WebSocket 
  useEffect(() => {
    const socket = new WebSocket('ws://localhost:3000');
    socket.onmessage = (e) => {
      setMsg(e.data); 
    }
  }, []);
  
  return <div>{msg}</div>  
}
// Vue 项目
methods: {
  sendMessage() {
    this.$socket.send('Hello from Vue!');
  }
},
sockets: {
  connect() {
    this.$socket = new WebSocket('ws://localhost:3000');
  }  
}
 4. 本地存储事件:使用本地存储监听 storage 事件在不同的浏览器窗口/标签页之间通信
 
//React:
js
// 发送消息
localStorage.setItem('message', 'Hello from React!');
// 接收消息
window.addEventListener('storage', (e) => {
  console.log(e.newValue); // Hello from Vue!
}); 
/Vue:
js
// 发送消息 
localStorage.setItem('message', 'Hello from Vue!');
// 接收消息
window.addEventListener('storage', (e) => {
  console.log(e.newValue); // Hello from React!
});
 5. 第三方消息代理:使用第三方服务如 Pusher、Socket.io 等在客户端之间传递消息
 
//Socket.io:
//React:
js
// 连接 Socket.io
const socket = io('http://localhost:4000');
// 发送消息
socket.emit('message', 'Hello from React!'); 
// 接收消息
socket.on('message', (msg) => {
  console.log(msg); // Hello from Vue!
});
//Vue:
js
// 连接 Socket.io
const socket = io('http://localhost:4000');
// 发送消息
socket.emit('message', 'Hello from Vue!');
// 接收消息
socket.on('message', (msg) => {
  console.log(msg); // Hello from React!
});
//Socket.io 服务器:
//js
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
io.on('connection', (socket) => {
  socket.on('message', (msg) => {
    socket.broadcast.emit('message', msg);
  });  
});
http.listen(4000);3.共享状态库
//在React中:javascript
import React from 'react';
import { createStore } from 'redux';
const initialState = { count: 0 };
function reducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    default:
      return state;
  }
}
const store = createStore(reducer);
function App() {
  const { count } = store.getState();
  function handleClick() {
    store.dispatch({ type: 'INCREMENT' });
  }
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increment</button>
    </div>
  );
}
export default App;
//在Vue中:javascript
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="handleClick">Increment</button>
  </div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
  computed: mapState(['count']),
  methods: mapActions(['increment']),
};
</script>在微前端中,不同的子应用之间可以通过多种方式进行通信和数据共享,不仅限于引用组件的方式。下面是一些常见的场景和解决方案:
1. 引用组件的方式在主应用中引用不同子应用的组件时,可以使用上面提到的自定义事件、消息总线或共享状态库等方式进行通信和数据共享。这种方式通常适用于子应用以组件的形式嵌入到主应用中的场景。
2. 路由的方式如果不同的子应用是通过路由的方式在主应用中引用的,可以使用URL参数、localStorage或cookie等方式进行通信和数据共享。例如,我们可以在URL参数中传递一些数据,或者使用localStorage或cookie来存储一些共享状态。
3. 独立运行的方式如果不同的子应用是独立运行的,它们之间无法直接进行通信和数据共享。但是,我们可以使用一些第三方工具或技术来实现跨域通信和数据共享,例如iframe、postMessage、WebSocket等。总之,不同的场景和需求需要选择不同的通信和数据共享方案。在实际应用中,我们需要根据具体情况来选择最合适的方案。













![[比赛简介]Predict Student Performance from Game Play](https://img-blog.csdnimg.cn/bd3f7b2f44e348ad8659b82c2911abca.png)





