Electron 学习笔记(常用功能记录)
一、简介
Electron = Chromium + Node.js + Native API
二、Hello World 示例
写好 index.html 后,写一个 main.js 作主进程:
var electron = require('electron');
var app = electron.app;var BrowserWindow = electron.BrowserWindow;var mainWindow = null;
app.on('ready', () => { mainWindow = new BrowserWindow({width: 800, height: 800}); mainWindow.loadFile('index.html'); mainWindow.on('closed', () => { mainWindow = null; })})三、渲染进程和本地文件读取
渲染进程:
使用渲染进程,则初始化 mainWindow 时,需要添加一个参数:
mainWindow = new BrowserWindow({ width: 800, height: 800, webPreferences: {nodeIntegration: true}}); 读取文件的渲染进程写法:
var fs = require('fs');window.onload = function() { fs.readFile('xxx.txt', (err, data) => { // action })}四、Remote 模块
使用 remote 模块可以让渲染进程使用主进程的方法,如新建页面。
先进行安装:
npm install --save @electron/remote main.js 中:
...const remote = require('@electron/remote/main')remote.initialize(); // 初始化...
app.on('ready', () => { ... remote.enable(mainWindow.webContents);}) render.js 中:
const {BrowserWindow} = require("@electron/remote");
window.onload = function() { btn.onclick = () => { newWin = new BrowserWindow({ width: 500, height: 500 }) newWin.on('closed', function() { newWin = null; }) }}五、创建主菜单
新建一个 menu.js:
注:menu.js 的功能在主进程中完成,因此不需要 remote
const { Menu } = require('electron');var template = [ { label: 'Outer Menu1', submenu: [ { label: 'Inner Menu11', // 绑定快捷键 accelerator: 'ctrl+n', // 绑定点击事件 click: () => { ... } }, {label: 'Inner Menu12'}, ] }, { label: 'Outer Menu2', submenu: [ {label: 'Inner Menu21'}, {label: 'Inner Menu22'}, ] }]
var m = Menu.buildFromTemplate(template);Menu.setApplicationMenu(m);六、创建右键菜单
在主 html 引用的 js 中绑定右键事件。
注:由于 html 属于渲染进程,因此此处要使用 remote
// 引用 js 中:const { BrowserWindow, Menu, getCurrentWindow } = require("@electron/remote");
...//固定写法:var rightMenuTemplate = [ {label: '复制', accelerator: 'ctrl+c'}, {label: '粘贴', accelerator: 'ctrl+v'},]
var m = Menu.buildFromTemplate(rightMenuTemplate);window.addEventListener('contextmenu', function(e) { e.preventDefault(); m.popup({window: getCurrentWindow()});})七、通过链接打开浏览器
使用 shell 可以完成该需求。
对应 js 中:
const { shell } = require('electron');
var theLink = document.querySelector('#website');theLink.onclick = function(e) { e.preventDefault(); shell.openExternal(this.getAttribute('href'));}八、嵌入网页与打开子窗口
嵌入网页(在 main.js):
const { BrowserView } = require('electron');
// 以 BrowserView 形式嵌入子网页var view = new BrowserView();mainWindow.setBrowserView(view);view.setBounds({ x: 0, y: 100, width: 700, height: 500 });view.webContents.loadURL('https://example.com'); 传统 html 打开新窗口:
// 打开新窗口var theLink = document.querySelector('#website');
var linkBtn = document.querySelector('#website-tab');linkBtn.onclick = function() { window.open(theLink.getAttribute('href'));}九、父子窗口通信
这里涉及的都是传统的 js 方法
特别注意:使用 window.open() 创建的子窗口方法受限,无法使用诸如 openDevtools() 等功能。
子窗口 js:
var popbtn = window.document.querySelector('#popbtn');popbtn.onclick = function(e) { window.opener.postMessage('这是一条来自子窗口的信息');} 父窗口 js:
window.addEventListener('message', (msg) => { let mytext = document.querySelector('#mytext'); // 注意 msg 是一个 json 对象 mytext.innerHTML = JSON.stringify(msg.data);})十、选择文件对话框
使用 dialog.showOpenDialog() 方法来实现。有两个参数,一个是基本属性,一个是回调。
注意:这里的对话框并不会提供文件载入功能,只是让用户确定打开的文件路径。
基本参数有:
- title
- defaultPath
- buttonLabel
- filters
- properties(打开文件的属性)
// 渲染进程中使用:const { dialog } = require('@electron/remote');
fileBtn.onclick = function() { dialog.showOpenDialog({ // 参数列表 title: '选择存档~', defaultPath: 'desktop', filters:[ {name: 'img', extensions:['jpg', 'png', 'gif']}, {name: 'text file', extensions:['c', 'cpp', 'py', 'txt', 'config']}, ], buttonLabel: '载入存档' }).then(result => { // 打开之后的操作 console.log(result); ... }).catch(err => { // 异常处理 console.error(err); })}十一、保存文件对话框
使用 showSaveDialog() 方法,与 showOpenDialog() 用法基本一致。
特别注意:触发对话框的元素最好不要被遮挡,否则可能会出现不可预知的崩溃!
保存文件可搭配 fs 模块使用。
const fs = require('fs');fs.writeFileSync(path, string);十二、消息对话框操作
使用 showMessageBox 方法。
参数:
- type:有 warning、info、question 和 error
- title:标题
- message:消息内容
- buttons:提供的选项(字符串列表)
const { dialog } = require('@electron/remote');
infoBtn.onclick = function() { dialog.showMessageBox({ type: 'info', title: '信息。', message: '只是一条提示信息。', buttons: ['哦?', '啊这...'], }).then(result => { console.log(result) }).catch(err => { console.error(err); })}十三、断网提醒功能
原生 html 事件监听实现实现。
window.addEventListener('online', function() { alert('又有网络了,好耶!');})window.addEventListener('offline', function() { alert('好像断线了哦...');})十四、底部消息通知
原生 html 方法。
var notifyBtn = document.querySelector('#notify-btn');var option = { title: '这是通知的标题', body: '这是通知的内容',};notifyBtn.onclick = function() { new window.Notification(option.title, option);}十五、注册全局快捷键
写在主进程中。
const { globalShortcut } = require('electron');
app.whenReady().then(() => { ... // 全局快捷键 globalShortcut.register('ctrl+g+l', function() { view.webContents.loadURL('https://bilibili.com'); }) // 检测是否注册成功 let isReisterMsg = globalShortcut.isRegistered('ctrl+g+l')?true:false; console.log(isReisterMsg); ...})
// 注销全局快捷键app.on('will-quit', () => { globalShortcut.unregister('ctrl+g+l'); globalShortcut.unregisterAll();})十六、剪贴板功能
使用 clipboard 模块的 writeText() 方法。
const { clipboard } = require('electron');
var copyBtn = document.querySelector('#copy-btn');// 除 writetext,也可以用其他方法实现复制图片等操作copyBtn.onclick = function() { clipboard.writeText('这是你复制的文本!~'); alert('复制成功!');}如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时