自定义菜单栏实现点击添加按钮打开渲染进程的Dialog.vue模态框

实现思路:渲染进程页面初始化后就通知主进程,然后把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>

效果如下:

相关推荐
薛定猫AI3 天前
【深度解析】Gemma Chat 本地 AI 编程 Agent:Electron + MLX + 开源模型的离线 Vibe Coding 实战
javascript·人工智能·electron
多秋浮沉度华年3 天前
electron 初始使用记录
javascript·arcgis·electron
阿波罗尼亚3 天前
桌面应用开发技术:NetBeans RCP / Eclipse RCP / JavaFX / Electron / Qt / Flutter Deskto
java·eclipse·electron
web打印社区4 天前
2026最新Web静默打印解决方案,无插件无预览,完美替代Lodop
前端·javascript·vue.js·electron·pdf
垚森4 天前
VibePlayer v1.3.3 更新:全新 Logo + 修复音乐库高亮 Bug
ai·electron
一叶飘零晋4 天前
【(一)Electron 使用之如何用vite+vue3搭建初始框架】
前端·javascript·electron
天天进步20154 天前
魔音漫创源码解析:架构总览:Electron 30 + React 18 + Zustand,构建桌面级影视生产工具
react.js·架构·electron
一叶飘零晋4 天前
【(二)Electron 使用之常用技巧】
javascript·electron·ecmascript
web打印社区6 天前
[特殊字符] 开源好物:web-print-pdf,让 Web 打印像调用接口一样简单!
前端·javascript·vue.js·electron
森总20206 天前
Electron 实战:utilityProcess 服务脚本热更新、用户目录优先启动与 asar 依赖解析
electron