实现思路:渲染进程页面初始化后就通知主进程,然后把event事件保存在该js文件外,当点击添加时因为是在其他位置,所以才要这样使用。然后点击添加后由主进程主动向渲染进程传递参数通知要做的操作。
代码如下:
// 第一步
// 进入主页面后给主进程通信 Home.vue
<script setup lang="ts" name="Home">
import {provide, ref, onMounted} from 'vue'
onMounted(async () => {
window.getSource.openDialog()
})
</script>
// preload.js
const {ipcRenderer, contextBridge} = require('electron')
const openDialog = () => ipcRenderer.send('on-opendialog-event')
contextBridge.exposeInMainWorld('getSource', {
openDialog
})
// 主进程 main.js
const { app, Menu, ipcMain } = require('electron')
// 监听 on-opendialog-event 事件
let event = null
ipcMain.on('on-opendialog-event', (e, message) => {
event = e;
})
// 第二步
// 主进程内自定义菜单点击 添加 后触发事件
const { app, Menu, ipcMain } = require('electron')
const isMac = process.platform === 'darwin'
// 监听 on-opendialog-event 事件
let event = null
ipcMain.on('on-opendialog-event', (e, message) => {
event = e;
})
const template = [
// { role: 'appMenu' }
...(isMac
? [{
label: app.name,
submenu: [
{ role: 'about' },
{ type: 'separator' },
{ role: 'services' },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideOthers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
}]
: []),
// { role: 'fileMenu' }
{
label: 'File',
submenu: [
isMac ? { role: 'close' } : { role: 'quit' }
]
},
// { role: 'editMenu' }
{
label: 'Edit',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
...(isMac
? [
{ role: 'pasteAndMatchStyle' },
{ role: 'delete' },
{ role: 'selectAll' },
{ type: 'separator' },
{
label: 'Speech',
submenu: [
{ role: 'startSpeaking' },
{ role: 'stopSpeaking' }
]
}
]
: [
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
])
]
},
// { role: 'viewMenu' }
{
label: 'View',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
},
// { role: 'windowMenu' }
{
label: 'Window',
submenu: [
{ role: 'minimize' },
{ role: 'zoom' },
...(isMac
? [
{ type: 'separator' },
{ role: 'front' },
{ type: 'separator' },
{ role: 'window' }
]
: [
{ role: 'close' }
])
]
},
{
role: 'help',
submenu: [
{
label: 'Learn More',
click: async () => {
const { shell } = require('electron')
await shell.openExternal('https://electronjs.org')
}
}
]
},
// 第一步看这个就可以
{
label: 'action',
submenu: [
{
label: '添加(打开dialog)',
click: () => {
// 作用: 主进程通知渲染进程
// 点击后主进程触发preload预加载内对应的事件,然后渲染进程触发打开弹窗
event.sender.send('on-renderer-event', 'add')
}
}
]
},
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
// preload.js处理主进程的事件event.sender.send('on-renderer-event', 'add')
const {ipcRenderer, contextBridge} = require('electron')
const openDialog = () => ipcRenderer.send('on-opendialog-event')
const onRendererEvent = () => {
return new Promise((resolve, reject) => {
ipcRenderer.on('on-renderer-event', (e, message) => {
// 主进程通知后就触发这个回调
resolve(message)
})
})
}
contextBridge.exposeInMainWorld('getSource', {
openDialog,
onRendererEvent
})
// 最后渲染进程Home.vue接收到传来的add,对类型进行监听后弹窗
<script setup lang="ts" name="Home">
import {provide, ref, onMounted} from 'vue'
let type = ref('');
onMounted(async () => {
window.getSource.openDialog()
// 主进程触发preload,preload通知这里执行
const res = await window.getSource.onRendererEvent()
type.value = res;
})
</script>
<template>
<main>
<div>home</div>
<SearchBar :type="type" />
<List />
</main>
</template>
// Searbar.vue监听type的值
<script setup lang="ts" name="SearchBar">
import {ref, inject, watch} from 'vue'
import Dialog from './Dialog.vue'
const props = defineProps(['type'])
const {show, setShow} = inject('on-show-event', {show: false, setShow: () => {}})
function handleShowDialog () {
setShow()
}
// 这里监听
watch(() => props.type, () => {
if (props.type == 'add') {
handleShowDialog();
}
})
</script>
<template>
<div class="search_bar">
<div @click="handleShowDialog">+</div>
<input placeholder="请输入关键词" type="text">
</div>
<Dialog></Dialog>
</template>
<style lang="less" scoped>
.search_bar {
width: 100%;
display: flex;
align-items: center;
height: 60px;
background-color: #ccc;
> div {
margin-left: 20px;
background-color: aqua;
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20px;
}
> input {
flex: 1;
}
}
</style>
效果如下: