文章目录
- 一. 目的
- 二.逻辑分析
- 三. 代码示例
"@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 window
const { 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 integration
nodeIntegration: true, // Electron 5.0.0 版本之后它将被默认false
// 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本.默认为 true
contextIsolation: false, // Electron 12 版本之后它将被默认true
nodeIntegrationInWorker: 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 integration
nodeIntegration: true, // Electron 5.0.0 版本之后它将被默认false
// 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本.默认为 true
contextIsolation: false, // Electron 12 版本之后它将被默认true
nodeIntegrationInWorker: 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 = data
return true;
});
ipcMain.handle('atlas-msg', async (event, data) =>{
console.log(data, "i am atlas")
atlasdata = data
return 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>