Electron 主进程与渲染进程通信

Posted 沿着路走到底

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Electron 主进程与渲染进程通信相关的知识,希望对你有一定的参考价值。

主进程与渲染进程之间通信

main.js

const  app, BrowserWindow, Menu, ipcMain  = require('electron')

console.log(process.platform)

// 创建窗口
function createWindow () 
  console.log('ready')
  // 创建主进程
  const mainWin = new BrowserWindow(
    title: '自定义菜单',
    show: false, // true:显示窗体,false: 不显示窗体
    width: 800,
    height: 400,
    webPreferences: 
      nodeIntegration: true, // 允许浏览器环境使用Node API
      enableRemoteModule: true, // 允许页面使用 remote
    
  )

  // 定义自己需要的菜单项
  const menuTemp = [
    
      label: 'send',
      click() 
        BrowserWindow.getFocusedWindow().webContents.send('mtp', '来自于自进程的消息')
      
    ,
    
      label: 'tool',
      click() 
        mainWin.webContents.openDevTools() // 打开调试面板
      
    
  ]

  // 生成菜单
  const menu = Menu.buildFromTemplate(menuTemp)

  // 将菜单添加到应用里
  Menu.setApplicationMenu(menu)

  // 在当前窗口中加载指定界面让它显示具体的内容
  mainWin.loadFile('index.html')
  

  mainWin.on('ready-to-show', () => 
    mainWin.show() // 在窗体完全加载完成后,显示窗体,避免白页现象
  )

  mainWin.on('close', () => 
    console.log('close')
    //mainWin = null
  )


// 当 app 启动之后,执行窗口创建等操作
app.on('ready', createWindow)

app.on('window-all-closed', () => 
  console.log('window-all-closed')
  app.quit()
)


// 主进程接收渲染进程传递的消息
ipcMain.on('msg1', (e, data) => 
  console.log(data)
  e.sender.send('msg1Re', 'msg1Re')
)

ipcMain.on('msg2', (e, data) => 
  console.log(data)
  e.returnValue = 'msg2Re'
)

index.js

const  ipcRenderer  = require('electron')

window.addEventListener('DOMContentLoaded', () => 
  const aBtn = document.getElementsByTagName('button')

  // 使用 异步API 在渲染进程中发送消息
  aBtn[0].addEventListener('click', () => 
    ipcRenderer.send('msg1', 'msg1')
  )

  // 使用 同步API 在渲染进程中发送消息
  aBtn[1].addEventListener('click', () => 
    const res = ipcRenderer.sendSync('msg2', 'msg2')
    console.log(res)
  )

 
  // 接收消息
  ipcRenderer.on('msg1Re', (e, data) => 
    console.log(data)
  )

  ipcRenderer.on('mtp', (e, data) => 
    console.log(data)
  )
)

渲染进程之间通信

渲染进程之间通信需要借助第三方完成数据中转

 

基于本地存储的渲染进程通信

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title></title>
</head>

<body>
  <h2>渲染进程间通信</h2>
  <button id="btn">打开窗口2</button>
  <script src="index.js"></script>
</body>
</html>

main.js

const  app, BrowserWindow, Menu, ipcMain  = require('electron')

console.log(process.platform)

// 定义全局变量存放主窗口 id
let mainWinId = null

// 创建窗口
function createWindow () 
  console.log('ready')
  // 创建主进程
  const mainWin = new BrowserWindow(
    title: '自定义菜单',
    show: false, // true:显示窗体,false: 不显示窗体
    width: 800,
    height: 400,
    webPreferences: 
      nodeIntegration: true, // 允许浏览器环境使用Node API
      enableRemoteModule: true, // 允许页面使用 remote
    
  )

  // 在当前窗口中加载指定界面让它显示具体的内容
  mainWin.loadFile('index.html')
  
  mainWinId = mainWin.id

  mainWin.on('ready-to-show', () => 
    mainWin.show() // 在窗体完全加载完成后,显示窗体,避免白页现象
  )

  mainWin.on('close', () => 
    console.log('close')
    //mainWin = null
  )


// 当 app 启动之后,执行窗口创建等操作
app.on('ready', createWindow)

app.on('window-all-closed', () => 
  console.log('window-all-closed')
  app.quit()
)


// 主进程接收渲染进程传递的消息
ipcMain.on('openWin2', () => 
  // 创建窗口
  const subWin1 = new BrowserWindow(
    width: 400,
    height: 300,
    parent: BrowserWindow.fromId(mainWinId),
    webPreferences: 
      nodeIntegration: true, // 允许浏览器环境使用Node API
      enableRemoteModule: true, // 允许页面使用 remote
    ,
  )

  subWin1.loadFile('subWin1.html')
)

index.js

const  ipcRenderer  = require('electron')

window.addEventListener('DOMContentLoaded', () => 
  const oBtn = document.getElementById('btn')

  oBtn.addEventListener('click', () => 
    ipcRenderer.send('openWin2')

    // 打开窗口后,存储数据在本地
    localStorage.setItem('name', 'name1')
  )
)

subWin1.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>窗口2</title>
</head>

<body>
  <h2>当前窗口2</h2>
  获取到index.html中的数据: <input type="text" id="txt">
  <script src="subWin1.js"></script>
</body>
</html>

subWin1.js

window.addEventListener('DOMContentLoaded', () => 
  const oInput = document.getElementById('txt')
  const val = localStorage.getItem('name')
  oInput.value = val
)

基于主进程的渲染进程通信

subWin1.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>窗口2</title>
</head>

<body>
  <h2>当前窗口2</h2>
  获取到index.html中的数据: <input type="text" id="txt">
  <br><br>
  <button id="btn">发送数据</button>
  <script src="subWin1.js"></script>
</body>
</html>

subWin1.js

const  ipcRenderer  = require('electron')

window.addEventListener('DOMContentLoaded', () => 
  // 发送数据给 index.js
  const oBtn = document.getElementById('btn')
  oBtn.addEventListener('click', () => 
    ipcRenderer.send('stm', 'stm')
  )

  // 接收数据
  ipcRenderer.on('its', (e, data) => 
    console.log(data)
  )
)

main.js

const  app, BrowserWindow, Menu, ipcMain  = require('electron')

console.log(process.platform)

// 定义全局变量存放主窗口 id
let mainWinId = null

// 创建窗口
function createWindow () 
  console.log('ready')
  // 创建主进程
  const mainWin = new BrowserWindow(
    title: '自定义菜单',
    show: false, // true:显示窗体,false: 不显示窗体
    width: 800,
    height: 400,
    webPreferences: 
      nodeIntegration: true, // 允许浏览器环境使用Node API
      enableRemoteModule: true, // 允许页面使用 remote
    
  )

  // 定义自己需要的菜单项
  const menuTemp = [
    
      label: 'send',
      click() 
        BrowserWindow.getFocusedWindow().webContents.send('mtp', '来自于自进程的消息')
      
    ,
    
      label: 'tool',
      click() 
        mainWin.webContents.openDevTools() // 打开调试面板
      
    
  ]

  // 生成菜单
  const menu = Menu.buildFromTemplate(menuTemp)

  // 将菜单添加到应用里
  //Menu.setApplicationMenu(menu)

  // 在当前窗口中加载指定界面让它显示具体的内容
  mainWin.loadFile('index.html')
  
  mainWinId = mainWin.id

  mainWin.on('ready-to-show', () => 
    mainWin.show() // 在窗体完全加载完成后,显示窗体,避免白页现象
  )

  mainWin.on('close', () => 
    console.log('close')
    //mainWin = null
  )


// 当 app 启动之后,执行窗口创建等操作
app.on('ready', createWindow)

app.on('window-all-closed', () => 
  console.log('window-all-closed')
  app.quit()
)


// 主进程接收渲染进程传递的消息
ipcMain.on('openWin2', (e, data) => 
  // 创建窗口
  const subWin1 = new BrowserWindow(
    width: 400,
    height: 300,
    parent: BrowserWindow.fromId(mainWinId),
    webPreferences: 
      nodeIntegration: true, // 允许浏览器环境使用Node API
      enableRemoteModule: true, // 允许页面使用 remote
    ,
  )

  subWin1.loadFile('subWin1.html')

  // 窗口加载完成后执行数据发送
  subWin1.webContents.on('did-finish-load', () => 
    subWin1.webContents.send('its', data)
  )
)

ipcMain.on('stm', (e, data) => 
  // 当前我们需要将 data 经过 main 进程转交给指定的渲染进程
  // 此时我们可以依据指定的窗口 ID 来获取对应的渲染进程,然后执行消息的发送
  const mainWin = BrowserWindow.fromId(mainWinId)
  mainWin.webContents.send('mti', data)
)

index.js

const  ipcRenderer  = require('electron')

window.addEventListener('DOMContentLoaded', () => 
  const oBtn = document.getElementById('btn')

  oBtn.addEventListener('click', () => 
    ipcRenderer.send('openWin2', 'from index.js')
  )

  // 接收消息
  ipcRenderer.on('mti', (e, data) => 
    console.log(data)
  )
)

1

以上是关于Electron 主进程与渲染进程通信的主要内容,如果未能解决你的问题,请参考以下文章

17-7-20-electron中主进程和渲染进程区别与通信

使用electron进行原生应用的打包---主进程与渲染进程之间的通信

07.electron-(渲染进程和主进程)通信

Electron 渲染进程主进程通信 01

Electron 渲染进程主进程通信 02

Electron 主进程和渲染进程