1. 目标
使用Electron创建桌面应用,发送端发送消息,接收端接收到消息后,在操作系统(windows 10) 上显示桌面通知,点击通知后在应用中显示详细信息。
2. 搭建项目
参考Electron9.x_Vue_调用DLL库 5.1,5.2 章节
vue create electron_rabbitmq
cd electron_rabbitmq
vue add electron-builder
npm i amqplib -S
3. 主进程中初始化 RabbitMQ模块
src/mainProcesses/rabbitmq.js 在主进程中与RabbitMQ进行通信, 该模块主要完成以下功能:
-
连接RabbitMQ服务器
-
注册一个handle, 当渲染进程需要发送消息的时候,可以通过 ipcRenderer 调用这个Handler:
// 主进程注册 ipcMain.handle('SEND_MQ_MESSAGE', async (event, msgObj) => {...} //渲染进程要发送消息的时候调用上面的Handle ipcRenderer.invoke('SEND_MQ_MESSAGE', sendContent)
-
当收到RabbitMQ消息的时候,推送消息到Windows 通知栏
let notification = new Notification({ title: msgTitle, // 通知的标题, 将在通知窗口的顶部显示 body: msgContent, // 通知的正文文本, 将显示在标题或副标题下面 silent: true // 在显示通知时是否发出系统提示音 }) notification.show()
-
当通知栏被点击的时候,主进程通知到渲染进程
// 主进程。 因为从主进程通知渲染进程的时候,需要知道向那个窗口发送,所以在这个模块初始化的时候,传入一个 webContents 对象 notification.on('click', e => { notification.close() console.log(e.sender.title) webContents.send('ON_NOTIFICATION_CLICK', { title: e.sender.title, body: e.sender.body }) }) // 渲染进程接收 主进程通知 ipcRenderer.on('ON_NOTIFICATION_CLICK', (event, message) => { window.alert('通知点击,通知标题:' + message.title) })
完整代码如下:
// 采用 promise 形式的API const amqp = require('amqplib') const { ipcMain, Notification } = require('electron') const serverConfig = { protocol: 'amqp', hostname: '192.168.1.201', port: 5672, username: 'qinye', password: 'qinye', vhost: '/electron' } let queueName = 'mq_hello' module.exports = { init(webContents) { function receivedMessageCallBack(content) { let { msgTitle, msgContent } = JSON.parse(content) console.log('收到消息:', msgTitle) let notification = new Notification({ title: msgTitle, // 通知的标题, 将在通知窗口的顶部显示 body: msgContent, // 通知的正文文本, 将显示在标题或副标题下面 silent: true // 在显示通知时是否发出系统提示音 }) notification.show() // 被点击之后通知渲染进程 notification.on('click', e => { notification.close() console.log(e.sender.title) webContents.send('ON_NOTIFICATION_CLICK', { title: e.sender.title, body: e.sender.body }) }) } amqp.connect(serverConfig).then( conn => { console.log('创建连接成功') conn.createChannel().then( ch => { console.log('创建Channel成功') ch.assertQueue(queueName, { durable: false // 队列不进行持久化 }) // 注册一个 渲染进程调用的方法 ipcMain.handle('SEND_MQ_MESSAGE', async (event, msgObj) => { console.log('sendMsg', msgObj) ch.sendToQueue(queueName, Buffer.from(JSON.stringify(msgObj))) }) ch.consume( queueName, function(msg) { receivedMessageCallBack(msg.content.toString()) }, { noAck: true } ) }, err => { console.log('创建Channel 错误:' + err) } ) }, err => { console.log('连接MQ Server 错误:' + err) } ) } }
4. 执行RabbitMQ初始化
background.js 中加入:
...
app.on('ready', async () => {
createWindow()
const rabbitmq = require('./mainProcesses/rabbitmq')
rabbitmq.init(win.webContents)
})
...
5. 渲染进程 App.vue
<template>
<div id="app">
<p>标题: <input type="text " v-model="msgTitle" /></p>
<p>内容: <input type="text " v-model="msgContent" /></p>
<p><button @click="sendMsg">发送消息</button></p>
</div>
</template>
<script>
import { ipcRenderer } from 'electron'
export default {
data() {
return {
msgTitle: '',
msgContent: ''
}
},
created() {
// 注册 主进程发送的事件
ipcRenderer.on('ON_NOTIFICATION_CLICK', (event, message) => {
window.alert('通知点击,通知标题:' + message.title)
})
},
methods: {
sendMsg() {
let sendContent = {
msgTitle: this.msgTitle,
msgContent: this.msgContent
}
ipcRenderer.invoke('SEND_MQ_MESSAGE', sendContent)
}
},
name: 'App',
components: {}
}
</script>
6. 执行效果
npm run electron:serve
点击"发送消息", Windows桌面收到消息:
点击桌面上的消息: