electron+vue+ts窗口间通信

文章目录

    • 一. 目的
    • 二.逻辑分析
    • 三. 代码示例


    "@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"

一. 目的

现有场景: 用户点击图,在新窗口展示实时数据
electron+vue+ts窗口间通信_第1张图片
electron+vue+ts窗口间通信_第2张图片


二.逻辑分析

vue作为纯渲染线程不具备操作本地数据以及窗口间通讯的功能,必须由经electron主进程解决.
因此官方为我们提供了IpcRederer向主进程发送消息的能力. 以及IpcMain主进程监听处理消息的能力.

由于ts和electron上下文隔离策略限制不允许直接使用request读取IpcRederer对象. 我们可以借助 usevue vue的第三方集成api综合库.读取ipcRederer

因此请注意
在vue渲染线程中 我们要参考的是usevue的官方文档 —> usevue
在electron主进程参考 —> electron

  1. 用户点击图谱
  2. A窗口向主进程发送打开B窗口请求
  3. 主进程收到A窗口消息, 创建B窗口.返回响应
  4. A窗口接收响应, 向生产者信道发送数据
  5. 主进程监听生产者信道接收数据,主进程将监听消息发送给消费者信道
  6. B窗口读取消费者信道数据

electron+vue+ts窗口间通信_第3张图片


三. 代码示例

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>

你可能感兴趣的:(electron,vue.js,javascript)