electron入门

菜单

Electron 里的菜单大体上分为三类:

  • 应用菜单:应用菜单通常位于应用程序的顶部,提供了用户可能用到的各种操作,如程序的快捷方式、常用的文件夹及系统命令等。
  • 上下文菜单:在应用里面点击右键看到的菜单。
  • Dock 菜单:只在 OSX 系统才有,通常功能较少,提供特别常用的功能

应用菜单

新建菜单

const menu = new Menu()

新建菜单项

const menuItem = new MenuItem({
    label: '菜单项名',
    click: handler,
    enabled,
    visible,
    type: normal|separator|submenu|checkbox|radio,
    role: copy|paste|cut|quit|...
})

添加菜单项

menu.append(new MenuItem({...}))
menu.append(new MenuItem({type: 'separator'}))
menu.append(new MenuItem({...}))

Electron 的所有内置的 role 如下:

  • undo: 撤销
  • redo:重做
  • cut:剪切
  • copy:复制
  • paste:粘贴
  • pasteAndMatchStyle
  • selectAll:全选
  • delete:删除
  • minimize:当前窗口最小化
  • close:关闭当前窗口
  • quit:退出应用程序
  • reload:刷新当前窗口
  • forceReload:强制刷新当前窗口,忽略缓存
  • toggleDevTools:打开或者关闭 devtool
  • togglefullscreen:进行全屏切换
  • resetZoom:重置窗口大小
  • zoomIn:放大窗口的10%.
  • zoomOut:缩小窗口的10%.

更多请参考: 菜单项 | Electron

新建menu.js

const { app, Menu } = require('electron')

const isMac = process.platform === 'darwin'

const template = [
  // { role: 'appMenu' }
  ...(isMac ? [{
    label: app.name,
    // submenu 代表下一级菜单
    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')
        }
      }
    ]
  }
]
// 从模板中创建菜单
const menu = Menu.buildFromTemplate(template)
// 设置为应用程序菜单
Menu.setApplicationMenu(menu)

main.js

const { app, BrowserWindow } = require("electron");

let win;
app.on("ready", () => {
  win = new BrowserWindow({
    width: 600,
    height: 600,
    webPreferences: {
      nodeIntegration: true, // 设置能在页面使用nodejs的API
      contextIsolation: false, // 关闭警告信息
    },
  });
  win.loadFile("./index.html");
  win.webContents.openDevTools();
  require("./menu");
});

 index.html

<html>
    <body>
        <div>菜单</div>
        <ol>
            <li>应用菜单</li>
            <li>上下文菜单</li>
            <li>Dock菜单</li>
        </ol>
    </body>
</html>

 运行npx electron main.js

注意的是:对于 OSX 而言,应用菜单的第一个菜单项是应用程序的名字,会使得 Edit App 这个菜单被覆盖掉。因此,我们需要针对 OSX 进行特殊处理,处理的过程通常是:

if (process.platform === 'darwin') {
    template.unshift({
        label: app.getName(),
        submenu: [
            {
                label: 'Quit',
                accelerator: 'CmdOrCtrl+Q',
                click() {
                    app.quit();
                }
            },
            // ...
        ]
    });
}

上下文菜单

上下文菜单(context menu)就是我们通常说的右键菜单。要创建由渲染器启动的菜单,请通过 IPC 发送所需的信息到主过程,并让主过程代替渲染器显示菜单。

renderer.js

//renderer.js
const { ipcRenderer } = require("electron");

window.addEventListener("contextmenu", (e) => {
  e.preventDefault();
  ipcRenderer.send("show-context-menu");
});

ipcRenderer.on("context-menu-command", (event, command) => {
  // ...
  console.log(event, command);
});

并且在index.html页面中引入将renderer.js 

 修改main.js

// ...
app.on("ready", () => {
  // ...
  handleIPC();
});

function handleIPC() {
  ipcMain.on("show-context-menu", (event) => {
    const contextTemplate = [
      {
        label: "Menu Item 1",
        click: () => {
          event.sender.send("context-menu-command", "menu-item-1");
        },
      },
      {
        label: "Cut",
        role: "cut",
      },
      {
        label: "Copy",
        role: "copy",
      },
    ];
    const menu = Menu.buildFromTemplate(contextTemplate);
    menu.popup(BrowserWindow.fromWebContents(event.sender));
  });
}

运行main.js后,右键: 

Dock菜单

修改main.js

const { app, BrowserWindow, ipcMain, Menu } = require("electron");

let win;
app.on("ready", () => {
  // ...
  createDockMenu();
  
});

const createDockMenu = () => {
  const dockTempalte = [
    {
      label: "New Window",
      click() {
        console.log("New Window");
      },
    },
    {
      label: "New Window with Settings",
      submenu: [{ label: "Basic" }, { label: "Pro" }],
    },
    {
      label: "New Command...",
    },
  ];

  const dockMenu = Menu.buildFromTemplate(dockTempalte);
  app.dock.setMenu(dockMenu);
};

运行后,右键icon

进程间通信

从渲染进程到主进程

Callback写法

  • ipcRenderer.send(channel, ...args)
  • ipcMain.on(channel, handler)

Promise写法

  • ipcRenderer.invoke(channel, ...args)
  • ipcMain.handle(channel, handler)

index.html

<script src="renderer.js"></script>

main.js

const { app, BrowserWindow, ipcMain } = require("electron");

let win;
app.on("ready", () => {
  win = new BrowserWindow({
    width: 300,
    height: 300,
    webPreferences: {
      nodeIntegration: true, //设置能在页面使用nodejs的API
      contextIsolation: false, //关闭警告信息
    },
  });
  win.loadFile("./index.html");
  handleIPC();
});
function handleIPC() {
  ipcMain.on("asynchronous-message", (event, arg) => {
    console.log(arg); // asynchronous ping
    event.reply("asynchronous-reply", "asynchronous pong");
  });

  ipcMain.on("synchronous-message", (event, arg) => {
    console.log(arg); // synchronous ping
    event.returnValue = "synchronous pong";
  });

  ipcMain.handle("my-invokable-ipc", async (event, ...args) => {
    console.log(...args);
  });
}

renderer.js

const { ipcRenderer } = require("electron");
console.log(ipcRenderer.sendSync("synchronous-message", "synchronous ping")); // synchronous pong

ipcRenderer.on("asynchronous-reply", (event, arg) => {
  console.log(arg); // asynchronous pong
});
ipcRenderer.send("asynchronous-message", "asynchronous ping");

ipcRenderer.invoke("my-invokable-ipc", 1, 2);

// 渲染进程
async function hanldeInvoke() {
  const result = await ipcRenderer.invoke("my-invokable-ipc", 1, 2);
  // ...
}

hanldeInvoke();

 运行npx electron main.js

从主进程到渲染进程

主进程通知渲染进程,因为只有一个主进程,可能有多个渲染进程,那么就需要找到具体的窗体内容, 主进程用 window 的 webContent 对象与网页内容进行交互

  • ipcRenderer.on(channel, handler)
  • webContents.send(channel)

main.js

const { app, BrowserWindow } = require("electron");

let win;
app.on("ready", () => {
  win = new BrowserWindow({
    width: 600,
    height: 600,
    webPreferences: {
      nodeIntegration: true, //设置能在页面使用nodejs的API
      contextIsolation: false, //关闭警告信息
    },
  });
  win.loadFile("./index.html");
  handleIPC();
});
function handleIPC() {
  win.webContents.send('do-some-render-work');
}

 renderer.js

const { ipcRenderer } = require("electron");

ipcRenderer.on('do-some-render-work', () => {
    alert('do some work');
})

 运行npx electron main.js

页面间(渲染进程与渲染进程间)通信 

通知事件

  • 利用主进程作为中转站
  • ipcRenderer.sendTo(webContentsId, channel, ...args)

数据共享

  • Web技术(localStorage、sessionStorage、indexedDB)
  • 使用remote(14.0.0版本后被废弃,改成@electron/remote)

利用主进程作消息中转

main.js

const { app, BrowserWindow, ipcMain } = require("electron");

let win, win2;
app.on("ready", () => {
  win = new BrowserWindow({
    width: 600,
    height: 600,
    webPreferences: {
      nodeIntegration: true, //设置能在页面使用nodejs的API
      contextIsolation: false, //关闭警告信息
    },
  });
  win.loadFile("./index.html");

  win2 = new BrowserWindow({
    width: 600,
    height: 600,
    webPreferences: {
      nodeIntegration: true, //设置能在页面使用nodejs的API
      contextIsolation: false, //关闭警告信息
    },
  });
  win2.loadFile("./index2.html");
  handleIPC();
});
function handleIPC() {
  ipcMain.on("message1", (event, arg) => {
    win2.webContents.send("do-some-work", arg);
  });
}

index2.html

<script src="renderer2.js"></script>

renderer.js

const { ipcRenderer } = require("electron");
ipcRenderer.send("message1", "hello!");

renderer2.js

const { ipcRenderer } = require("electron");

ipcRenderer.on('do-some-work', (event, arg) => {
    console.log('renderer2 handle ' + arg);
})

利用ipcRenderer.sendTo

先安装@electron/remote

main.js

const { app, BrowserWindow, ipcMain } = require("electron");
// 初始化
require("@electron/remote/main").initialize();

let win, win2;
app.on("ready", () => {
  win = new BrowserWindow({
    width: 600,
    height: 600,
    webPreferences: {
      nodeIntegration: true, //设置能在页面使用nodejs的API
      contextIsolation: false, //关闭警告信息
    },
  });
  win.loadFile("./index.html");
  require("@electron/remote/main").enable(win.webContents);

  win2 = new BrowserWindow({
    width: 600,
    height: 600,
    webPreferences: {
      nodeIntegration: true, //设置能在页面使用nodejs的API
      contextIsolation: false, //关闭警告信息
    },
  });
  win2.loadFile("./index2.html");

  global.sharedObject = {
    win2WebContentsId: win2.webContents.id,
  };

});

 renderer.js

const { ipcRenderer } = require("electron");
const remote = require('@electron/remote');

// 利用remote 、sendTo
let sharedObject = remote.getGlobal("sharedObject");
let win2WebContentsId = sharedObject.win2WebContentsId;
ipcRenderer.sendTo(win2WebContentsId, "do-some-work", "hello!");

renderer2.js

const { ipcRenderer } = require("electron");

ipcRenderer.on("do-some-work", (event, arg) => {
  console.log("renderer2 handle " + arg);
});

利用本地存储进行通信

renderer.js

window.onload = function () {
  localStorage.setItem("message", "hello!");
};

 renderer2.js

window.onload = function () {
  var msg = localStorage.getItem("message");
  alert(msg);
};

参考资料:

ipcMain | Electron

https://segmentfault.com/a/1190000020521879

Electron开发实战-极客时间

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Electron 入门指的是学习如何使用 Electron 框架来开发跨平台的桌面应用程序。首先需要了解 Electron 的基本概念和架构,包括主进程和渲染进程、应用程序的生命周期等。然后需要学习如何使用 HTML、CSS 和 JavaScript 来开发界面和逻辑,并且掌握 Electron 提供的 API 来访问操作系统的底层功能,比如文件系统、网络、窗口管理等。最后需要了解如何打包和发布应用程序,以及如何调试和测试应用程序。 ### 回答2: Electron 是一个用于构建跨平台桌面应用程序的开源框架。它使用 HTML、CSS 和 JavaScript 来创建桌面应用程序,并且可以在不同的操作系统上运行,如 Windows、Mac 接来和 Linux。 学习 Electron 入门可以按照以下步骤进行: 1. 准备开发环境:首先要安装 Node.js 和 npm,它们用于安装 Electron。可以在官方网站上下载并安装最新版本的 Node.js。安装完成后,打开终端或命令提示符窗口,运行命令 `npm install -g electron` 安装 Electron。 2. 创建一个新项目:在合适的目录下创建一个新的文件夹作为项目文件夹。在终端或命令提示符中,切换到项目文件夹,并运行命令 `npm init` 创建一个新的 npm 项目。按照提示一步一步地填写项目信息。完成后,会生成一个 `package.json` 文件,用于管理项目依赖和配置。 3. 安装必要的依赖:现在,需要安装 Electron 的依赖。在终端或命令提示符中运行命令 `npm install electron --save-dev` 安装 Electron。 4. 编写主进程代码:在项目文件夹中创建一个新的 JavaScript 文件,作为 Electron 的主进程代码。主进程代码负责启动应用程序并管理窗口。 5. 编写页面代码:创建一个新的 HTML 文件,用于作为应用程序的主页面。 6. 运行 Electron:在终端或命令提示符中,切换到项目文件夹,并运行命令 `electron .` 启动应用程序。应用程序的窗口将会显示出来,同时运行主进程和页面代码。 通过上述步骤,可以快速入门 Electron,并开始构建跨平台桌面应用程序。可以通过学习 Electron 的文档、示例代码和社区资源深入了解和掌握 Electron 的更多特性和功能。 ### 回答3: electron是一种跨平台的开源桌面应用程序框架,可用于构建基于HTML、CSS和JavaScript的桌面应用程序。它通过将现代Web技术与Node.js的强大功能相结合,提供了一种简单而又强大的方式来开发可在Windows、Mac和Linux上运行的桌面应用程序。 要入门electron,首先需要安装electron的开发环境。可以通过npm(Node.js的包管理器)来安装所需的工具和依赖项。然后,创建一个新的electron项目,并安装electron所需的依赖包。接下来,可以使用任何常见的Web开发工具(如HTML、CSS和JavaScript)来进行应用程序的开发。 在electron中,应用程序的主进程由一个main.js文件来控制,而渲染进程由HTML和JavaScript文件来控制。通过main.js文件,可以创建一个主窗口并控制窗口的行为。在渲染进程中,可以使用Web技术来构建应用程序的用户界面,例如使用HTML构建页面结构,使用CSS样式化页面,使用JavaScript实现交互和动态效果。 electron还提供了许多API和功能,使开发者能够与底层操作系统进行交互,例如访问文件系统、显示原生对话框、打开外部链接等。此外,electron还支持构建可打包为独立安装包的应用程序,以便更方便地在不同操作系统上分发和部署应用程序。 总的来说,入门electron需要安装开发环境,创建项目,使用常见的Web技术进行开发,并利用electron提供的API和功能来构建强大的跨平台桌面应用程序。由于其简单易用的特点,electron已成为许多开发者喜爱的桌面应用程序开发框架之一。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值