1. 概述
再electron中,進(jìn)程間的通信通過ipcMain和ipcRenderer模塊,這些通道是任意和雙向的
1.1. 什么是上下文隔離進(jìn)程
ipc通道是通過預(yù)加載腳本綁定到window對(duì)象的electron對(duì)象屬性上的
2. 通信方式
2.1. ipcMain(也就是渲染進(jìn)程向主進(jìn)程的通信 單向)
- 如果要將渲染器進(jìn)程發(fā)送的主進(jìn)程,我們使用ipcRenderer.send()在渲染進(jìn)程中發(fā)送信息,然后在主進(jìn)程中通過ipcMain.on來接收到渲染進(jìn)程所發(fā)送的信息
2.2. 渲染器進(jìn)程到主進(jìn)程(雙向)
- 雙向 IPC 的一個(gè)常見應(yīng)用是從渲染器進(jìn)程代碼調(diào)用主進(jìn)程模塊并等待結(jié)果。 這可以通過將 ipcRenderer.invoke 與 ipcMain.handle 搭配使用來完成。
2.3. 主進(jìn)程到渲染進(jìn)程
- 將消息從主進(jìn)程發(fā)送到渲染器進(jìn)程時(shí),需要指定是哪一個(gè)渲染器接收消息。 消息需要通過其 WebContents 實(shí)例發(fā)送到渲染器進(jìn)程。 此 WebContents 實(shí)例包含一個(gè) send 方法,其使用方式與 ipcRenderer.send 相同。
3. 在electron-vite腳手架中進(jìn)行統(tǒng)一使用
當(dāng)用electron-vite腳手架搭建完項(xiàng)目之后在src文件夾下有三個(gè)文件夾
他們分別是:
- main 主進(jìn)程
- preload 預(yù)加載腳本
- renderer ui界面/渲染進(jìn)程
3.1. ipcMain(也就是渲染進(jìn)程向主進(jìn)程的通信 單向)
- 首先在main.ts中新建ipc.ts文件來寫入ipc通道和src目錄在新建common(和main文件夾同級(jí))來綁定ipc事件信息
//我們?cè)谶@個(gè)中定義ipc的事件名稱,翻遍后續(xù)的事件管理
export enum IpcEvents{
SAYHELLO="sayhello"
}
//引入相關(guān)的事件名稱
import {ipcMain} from 'electron'
import {IpcEvents} from "../common/ipcEvents";
//ipc事件注冊(cè)函數(shù)
const register=async ():Promise<void>=>{
ipcMain.on(IpcEvents.SAYHELLO,async (e)=>{
console.log('hello')
})
}
export default {register}
最后一步我們需要再main/index.ts主進(jìn)程文件中注冊(cè)ipc通道事件
//首先引入我們的ipc文件
import ipc from './ipc'
//然后我們找到這個(gè)函數(shù)
app.whenReady().then(async () => {
// Set app user model id for windows
...
...
await ipc.register() //需要注意的是我們要在這兒createWindwo()函數(shù)之前注冊(cè)ipc事件(也就是在創(chuàng)建窗口之前注冊(cè))
createWindow()
...
...
})
在渲染進(jìn)程中使用
<template>
<div class="home">
<n-button @click="clickHandler">點(diǎn)擊</n-button>
</div>
</template>
<script lang="ts" setup>
import {IpcEvents} from "../../../../../common/ipcEvents";
//在此處點(diǎn)擊事件
const clickHandler=()=>{
window.electron.ipcRenderer.send(IpcEvents.SAYHELLO) //此處調(diào)用事件
}
</script>
<style lang="scss" scoped>
.home{
height: 100%;
padding: 16px;
}
</style>
當(dāng)我們點(diǎn)擊后發(fā)現(xiàn)控制臺(tái)出現(xiàn)相應(yīng)的打印輸出后表示注冊(cè)成功
3.1.1. 如何進(jìn)行傳參
- 我們?cè)趇pc通道中進(jìn)行參數(shù)/數(shù)據(jù)傳遞的時(shí)候,建議使用JSON序列化
<template>
<div class="home">
<n-button @click="clickHandler">點(diǎn)擊</n-button>
</div>
</template>
<script lang="ts" setup>
import {IpcEvents} from "../../../../../common/ipcEvents";
const datalist=[
{name:"yu",age:23,sex:"男"},
{name:"chao",age:23,sex:"女"},
{name:"zhi",age:23,sex:"未知"},
{name:"wang",age:24,sex:"男"},
]
const clickHandler=()=>{
const data=JSON.stringify(datalist)
window.electron.ipcRenderer.send(IpcEvents.SAYHELLO,data)
}
</script>
<style lang="scss" scoped>
.home{
height: 100%;
padding: 16px;
}
</style>
import {ipcMain} from 'electron'
import {IpcEvents} from "../common/ipcEvents";
const register=async ():Promise<void>=>{
ipcMain.on(IpcEvents.SAYHELLO,async (e,data)=>{
const dataList=JSON.parse(data)
console.log(dataList)
})
}
export default {register}
點(diǎn)擊后會(huì)發(fā)現(xiàn)在控制臺(tái)中中文會(huì)亂碼
electron中中文亂碼解決方案
在啟動(dòng)命令之前添加chcp 65001
解決electron控制臺(tái)下打印中文亂碼
"dev": "chcp 65001 && electron-vite dev",
?文章來源地址http://www.zghlxwxcb.cn/news/detail-816793.html
現(xiàn)在我們重新啟動(dòng)項(xiàng)目,可以清除的看到中文不會(huì)亂碼
3.2. 主進(jìn)程向渲染進(jìn)程通信
我們首先在src/renderer/src下新建文件夾名hook
然后新建文件useIpcRendererOn.ts
import { onUnmounted } from 'vue'
//這兒要注意引入的ipc事件的地址,然后無腦粘貼
import { IpcEvents } from '../../../common/ipcEvents'
type IpcRendererListener = (event: any, ...args: any[]) => void
//用于監(jiān)聽主進(jìn)程向渲染進(jìn)行雙向的通信
export default function useIpcRendererOn(
channel: IpcEvents,
listener: IpcRendererListener
): any {
const ipc = (window as any).electron.ipcRenderer
onUnmounted(() => {
ipc.removeListener(channel, listener)
})
return (window as any).electron.ipcRenderer.on(channel, listener)
}
重新定義新的事件名稱
//我們?cè)谶@個(gè)中定義ipc的事件名稱,翻遍后續(xù)的事件管理
export enum IpcEvents{
SAYHELLO="sayhello",
SAYWORLD="sayworld"
}
住進(jìn)程向渲染進(jìn)程發(fā)送消息
import {ipcMain} from 'electron'
import {IpcEvents} from "../common/ipcEvents";
const register=async ():Promise<void>=>{
ipcMain.on(IpcEvents.SAYHELLO,async (e,data)=>{
const dataList=JSON.parse(data)
console.log(dataList)
const world=JSON.stringify([
{
name:"這個(gè)是主進(jìn)程傳遞過來的",
value:1
}
])
//在這兒向渲染進(jìn)程發(fā)送信息
e.sender.send(IpcEvents.SAYWORLD,world)
})
}
export default {register}
我們?cè)阡秩具M(jìn)程中來監(jiān)聽主程序的發(fā)送的數(shù)據(jù)
<template>
<div class="home">
<n-button @click="clickHandler">點(diǎn)擊</n-button>
</div>
</template>
<script lang="ts" setup>
import {IpcEvents} from "../../../../../common/ipcEvents";
import useIpcRendererOn from "../../../hook/useIpcRendererOn";
const datalist=[
{name:"yu",age:23,sex:"男"},
{name:"chao",age:23,sex:"女"},
{name:"zhi",age:23,sex:"未知"},
{name:"wang",age:24,sex:"男"},
]
const clickHandler=()=>{
const data=JSON.stringify(datalist)
window.electron.ipcRenderer.send(IpcEvents.SAYHELLO,data)
}
//用來監(jiān)聽渲染進(jìn)程發(fā)送的信息
useIpcRendererOn(IpcEvents.SAYWORLD,async (_,data)=>{
const list=JSON.parse(data)
console.log(list)
})
</script>
<style lang="scss" scoped>
.home{
height: 100%;
padding: 16px;
}
</style>
當(dāng)我們點(diǎn)擊按鈕后回清晰看到在頁(yè)面的開發(fā)者工具中打印出來主進(jìn)程中傳遞過來的數(shù)據(jù)
上述行為整體剖析
- 我們首先通過在頁(yè)面中進(jìn)行點(diǎn)擊來觸發(fā)window.electron.ipcRenderer.send(IpcEvents.SAYHELLO,data)中的SAYHELLO事件
- 然后在住進(jìn)程中通過 ipcMain.on(IpcEvents.SAYHELLO)接收到相對(duì)應(yīng)的點(diǎn)擊事件并打印(打印在控制臺(tái))
- 然后再通過e.sender.send(IpcEvents.SAYWORLD)向渲染進(jìn)程發(fā)送信息
- 渲染進(jìn)程通過useIpcRendererOn(IpcEvents.SAYWORLD),來監(jiān)聽SAYWORLD主進(jìn)程發(fā)送的事件
由以上四步在住進(jìn)程中形成了統(tǒng)一的閉環(huán)操作。
以上情況幾乎能夠完成所有的ipc通信操作,還有一種情況后續(xù)再說
3.3. 擇日不如撞日(最后一種方式)雙向奔赴
首先在ipcEvents.ts中注冊(cè)一個(gè)事件名稱
export enum IpcEvents{
SAYHELLO="sayhello",
SAYWORLD="sayworld",
SAYTHANKYOU='Thankyou'
}
我們首先在渲染界面發(fā)送消息
<template>
<div class="home">
<n-button @click="clickHandler">點(diǎn)擊</n-button>
<n-button @click="sayTankyouHandler">說謝謝</n-button>
</div>
</template>
<script lang="ts" setup>
import {IpcEvents} from "../../../../../common/ipcEvents";
import useIpcRendererOn from "../../../hook/useIpcRendererOn";
const datalist=[
{name:"yu",age:23,sex:"男"},
{name:"chao",age:23,sex:"女"},
{name:"zhi",age:23,sex:"未知"},
{name:"wang",age:24,sex:"男"},
]
const clickHandler=()=>{
const data=JSON.stringify(datalist)
window.electron.ipcRenderer.send(IpcEvents.SAYHELLO,data)
}
useIpcRendererOn(IpcEvents.SAYWORLD,async (_,data)=>{
const list=JSON.parse(data)
console.log(list)
})
const sayTankyouHandler=async ()=>{
//這兒發(fā)送消息,向主進(jìn)程
await window.electron.ipcRenderer.invoke(IpcEvents.SAYTHANKYOU).then((data: string) => {
//data便是渲染進(jìn)程中然會(huì)過來的數(shù)據(jù)
console.log(data)
})
}
</script>
<style lang="scss" scoped>
.home{
height: 100%;
padding: 16px;
}
</style>
住進(jìn)程中接收并返回
import {ipcMain} from 'electron'
import {IpcEvents} from "../common/ipcEvents";
const register=async ():Promise<void>=>{
ipcMain.on(IpcEvents.EVPLAY,async (e,data)=>{
const dataList=JSON.parse(data)
console.log(dataList)
const world=JSON.stringify([
{
name:"這個(gè)是主進(jìn)程傳遞過來的",
value:1
}
])
e.sender.send(IpcEvents.SAYWORLD,world)
})
//這個(gè)便是進(jìn)行的雙向通信說謝謝
ipcMain.handle(IpcEvents.SAYTHANKYOU,()=>{
return '謝謝'
})
}
export default {register}
我們可以看見非常的有禮貌,那你呢?
值得注意的是:
- 以上操作我們都是在electron-vite的腳手架下完成的,electron-vite已經(jīng)完成了文件預(yù)加載的任務(wù)(也就是說已經(jīng)把electron的對(duì)象綁定到了window對(duì)象上)
- 如果您自己搭建electron那么需要自己創(chuàng)建預(yù)加載文件。
- 還有另外一種情況就是,我們此預(yù)加載文件是在主窗口下引入,如果新打開窗口不是主窗口那么需要在新打開窗口中重新引入預(yù)加載文件,否則Ipc通信不可使用
為了解決紅色方框的第三個(gè)問題,以示誠(chéng)意貼張圖片
以上便是完整的ipc通信,說謝謝文章來源:http://www.zghlxwxcb.cn/news/detail-816793.html
?
到了這里,關(guān)于electron-vite中的ipc通信的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!