前面讲到了微前端的应用:(94条消息) 微前端应用(qiankun+umi+antd)_他夏了夏天吖的博客-CSDN博客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等。总之,不同的场景和需求需要选择不同的通信和数据共享方案。在实际应用中,我们需要根据具体情况来选择最合适的方案。