文章目录
- 一. 目的
- 二.逻辑分析
- 三. 代码示例
"@types/node": "^20.3.1","@vitejs/plugin-vue": "^4.1.0","@vueuse/electron": "^10.2.1","electron": "^25.2.0","electron-packager": "^17.1.1","typescript": "^5.0.2","vite": "^4.3.9","vue-tsc": "^1.4.2"
一. 目的
现有场景: 用户点击图,在新窗口展示实时数据
二.逻辑分析
vue作为纯渲染线程不具备操作本地数据以及窗口间通讯的功能,必须由经electron主进程解决.
因此官方为我们提供了IpcRederer向主进程发送消息的能力. 以及IpcMain主进程监听处理消息的能力.
由于ts和electron上下文隔离策略限制不允许直接使用request读取IpcRederer对象. 我们可以借助 usevue vue的第三方集成api综合库.读取ipcRederer
因此请注意
在vue渲染线程中 我们要参考的是usevue的官方文档 —> usevue
在electron主进程参考 —> electron
- 用户点击图谱
- A窗口向主进程发送打开B窗口请求
- 主进程收到A窗口消息, 创建B窗口.返回响应
- A窗口接收响应, 向生产者信道发送数据
- 主进程监听生产者信道接收数据,主进程将监听消息发送给消费者信道
- B窗口读取消费者信道数据
三. 代码示例
A.vue
import {useIpcRenderer} from "@vueuse/electron";
const ipcRenderer = useIpcRenderer();async function openTextBox() {await res.open()console.log(res.data.value)// 向发送数据resp.value = ipcRenderer.invoke('product-msg', res.data.value)if(resp.value){// 创建新窗口ipcRenderer.send('textBox', '/browse')resp.value=false}
}
Main.js/Main.ts 主进程
// Modules to control application life and create native browser windowconst { app, BrowserWindow, ipcMain,Menu } = require('electron')
// import './src/store/index'
const path = require('path')
// const winURL = process.env.NODE_ENV === 'development' ? 'http://localhost:8080' : `file://${path.join(__dirname, './dist/index.html')}`let mainWindow
let textdata
let atlasdata
let textBox;
function createWindow() {// Create the browser window.mainWindow = new BrowserWindow({width: 1280,height: 1024,minWidth: 600,minHeight: 600,title: '局部放电监控中心',// autoHideMenuBar: true, // 自动隐藏菜单栏webPreferences: {// 是否启用Node integrationnodeIntegration: true, // Electron 5.0.0 版本之后它将被默认false// 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本.默认为 truecontextIsolation: false, // Electron 12 版本之后它将被默认truenodeIntegrationInWorker: true,// 禁用同源策略,允许跨域webSecurity: false,preload: path.join(__dirname, 'preload.js'),}})// and load the index.html of the app.// 访问路径,需要配合路由转发到vue页面mainWindow.loadFile('./dist/index.html')// Open the DevTools.mainWindow.webContents.openDevTools({mode:'right'})// 监听窗口关闭mainWindow.on('window-close', function () {mainWindow.close();})// 主进程上下文渲染时机 did-finish-load 窗口导航栏渲染完成触发mainWindow.webContents.on('did-finish-load', () => {console.log("主进程渲染,主窗口加载完毕")})}// 左上角导航菜单栏
const menu = Menu.buildFromTemplate([{label: app.name,submenu: [{click: () => textBox.webContents.send('customer-msg', textdata),label: 'Increment'},]}])
Menu.setApplicationMenu(menu)// 监听textBox消息
ipcMain.on('textBox', function (event, data) {console.log("接收")textBox = new BrowserWindow({width: 1280,height: 1024,minWidth: 600,minHeight: 600,parent: mainWindow, // mainWindow是主窗口frame: true, // 有边框title: '查看',autoHideMenuBar: true, // 自动隐藏菜单栏webPreferences: {// 是否启用Node integrationnodeIntegration: true, // Electron 5.0.0 版本之后它将被默认false// 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本.默认为 truecontextIsolation: false, // Electron 12 版本之后它将被默认truenodeIntegrationInWorker: true,// 禁用同源策略,允许跨域webSecurity: false,preload: path.join(__dirname, 'preload.js'),}})// console.log(data,"---2323---")// textBox.loadURL('http://127.0.0.1:3000/#/add') // 此处写 你要打开的路由地址textBox.loadFile('./dist/index.html', {hash: '#' + data});// 监听textBox窗口关闭textBox.on('closed', () => {textBox == null;})// Open the DevTools.textBox.webContents.openDevTools({ mode: 'right' })// textBox.webContents.on('did-finish-load', () => {// console.log("渲染进程渲染,新窗口加载完毕")// textBox.webContents.send('customer-msg', textdata)// })// did-stop-loading 打开新窗口触发3次, 关闭触发1次textBox.webContents.on('did-stop-loading', () => {console.log("渲染进程渲染,新窗口加载完毕")textBox.webContents.send('customer-msg', textdata)textBox.webContents.send('atlas-customer-msg', atlasdata)})
})// 监听 product-msg 信道消息
ipcMain.handle('product-msg', async (event, data) =>{console.log(data, "i am data")textdata = datareturn true;
});
ipcMain.handle('atlas-msg', async (event, data) =>{console.log(data, "i am atlas")atlasdata = datareturn true;
});// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)app.on('activate', function () {// On macOS it's common to re-create a window in the app when the// dock icon is clicked and there are no other windows open.if (BrowserWindow.getAllWindows().length === 0) createWindow()})// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {if (process.platform !== 'darwin') app.quit()
})// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
B.vue
<template><span>{{ data }}</span>
</template><script setup lang="ts">
import { ref} from "vue";
import {useIpcRenderer} from "@vueuse/electron";const ipcRenderer = useIpcRenderer();const data = ref('')ipcRenderer.on('customer-msg', ((event, arg) => {data.value = arg;console.log(arg) }))
</script><style></style>