## Electron Quick Start ``` # 克隆这仓库 $ git clone https://github.com/electron/electron-quick-start # 进入仓库 $ cd electron-quick-start # 安装依赖库 $ npm install # 运行应用 $ npm start ``` ## 使用IPC进行GUI与原生APP进行通讯 在main.js里添加下面的代码,从通道订阅消息: ``` var ipc = require('ipc'); ipc.on('close-main-window', function () { app.quit(); }); ``` 引入ipc模块后,通过通道订阅消息就变得很简单,on()方法设置订阅的通道名,定义回调函数。 渲染进程要通过通道发送消息,将下面代码加入index.js: ``` var ipc = require('ipc'); var closeEl = document.querySelector('.close'); closeEl.addEventListener('click', function () { ipc.send('close-main-window'); }); ``` 同样,我们引入ipc模块,给关闭按钮的元素绑定一个click事件。当点击关闭按钮时,通过「close-main-window」通道的send()方法发送消息。 ## 全局快捷键 ``` var globalShortcut = require('global-shortcut'); app.on('ready', function() { ... // existing code from earlier globalShortcut.register('ctrl+shift+1', function () { mainWindow.webContents.send('global-shortcut', 0); }); globalShortcut.register('ctrl+shift+2', function () { mainWindow.webContents.send('global-shortcut', 1); }); }); ``` ``` ipc.on('global-shortcut', function (arg) { var event = new MouseEvent('click'); soundButtons[arg].dispatchEvent(event); }); ``` ## 保存用户配置 使用nconf模块 ``` npm install --save nconf ``` ``` var nconf = require('nconf').file({file: getUserHome() + '/sound-machine-config.json'}); function saveSettings(settingKey, settingValue) { nconf.set(settingKey, settingValue); nconf.save(); } function readSettings(settingKey) { nconf.load(); return nconf.get(settingKey); } function getUserHome() { return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME']; } module.exports = { saveSettings: saveSettings, readSettings: readSettings }; ``` ## 系统托盘 ``` var remote = require('remote'); var Tray = remote.require('tray'); var Menu = remote.require('menu'); var path = require('path'); var trayIcon = null; if (process.platform === 'darwin') { trayIcon = new Tray(path.join(__dirname, 'img/tray-iconTemplate.png')); } else { trayIcon = new Tray(path.join(__dirname, 'img/tray-icon-alt.png')); } var trayMenuTemplate = [ { label: 'Sound machine', enabled: false }, { label: 'Settings', click: function () { ipc.send('open-settings-window'); } }, { label: 'Quit', click: function () { ipc.send('close-main-window'); } } ]; var trayMenu = Menu.buildFromTemplate(trayMenuTemplate); trayIcon.setContextMenu(trayMenu); ``` ## 打包应用 >摘自https://www.jianshu.com/p/f134878af30f 安装electron-package ``` npm install electron-package --save-dev ``` 添加scrip命令 ,用于打包electron app。 ``` "scripts": { "start": "electron .", "build": "electron-packager . hello_electron --platform=darwin --arch=x64 --ignore=node_modules/electron-*", }, ``` **electron-packager命令格式** ``` electron-packager 项目目录 app名称 --platform=平台 --arch=架构 --ignore=要忽略的目录或文件 arch ia32 , x64 , armv7l , all plateform linux , win32 , darwin , mas , all OS X (also known as darwin) Mac App Store (also known as mas) ``` 执行命令npm run build,将得到如下结果 ### electron-builder与electron-packager的区别 使用electron-builder打包应用是安装包方式,而不想electron-packager打包之后直接是一个可文件夹,交给所有的文件暴露出来。由electron-builder打出的包更为轻量,并且可以打包出不暴露源码的setup安装程序 ## 压缩源码 为避免源代码泄露,可对源码进行压缩。 **安装electron-asar** ``` npm install electron-asar --save-dev ``` **添加scrip命令 ,用于压缩源代码。** ``` "scripts": { "start": "electron .", "build": "electron-packager . hello_electron --platform=darwin --arch=x64 --ignore=node_modules/electron-*", "package":"asar pack hello_electron-darwin-x64/hello_electron.app/Contents/Resources/app hello_electron-darwin-x64/hello_electron.app/Contents/Resources/app.asar" }, ``` **asar 命令格式** asar pack 执行npm run package将得到app.asar文件,此时可将app文件删除。 ## Electron启动node.js服务器 1.直接在index.html中启动外部的node.js服务器 2.将原生的node.js服务器代码使用module.exports = () => {}导出,之后在electron的main.js中直接导入 ``` app.server = require(__dirname + '/app/app')(); ``` ## 不迁移项目就可以打包双版本的可行方案 作者并未提供web开发的支持,但是提供了非常好的web打包支持。 只要写好逻辑我们可以不用迁移项目就可以打包桌面项目和web项目。 process.env.IS_WEB是暴露的一个全局变量,我们可以在渲染进程中获取,项目在electron环境下,返回false。否则为true。于此,我们可以通过设置她的值来达到web dev的效果,也可以处理不同环境的不同逻辑,一些示例: ![image](https://upload-images.jianshu.io/upload_images/3765249-cae045ed68c41067.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![image](https://upload-images.jianshu.io/upload_images/3765249-e8f7f6ac49fdf050.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![image](https://upload-images.jianshu.io/upload_images/3765249-a48751e6cf2d88e3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ## 打开新窗口的“最佳”做法 1.使用webview, allowpopups变量控制是否拦截新弹出的窗口 下面的例子,是webview允许.open/.showModalDialog/.showModelessDialog的例子: electron的index.html:(重点是参数allowpopups) ``` ``` 原文:https://newsn.net/say/electron-webview-window-open.html 2.因为是webpack配置,入口只有index.html ,所以打开新窗口,一般会再配置一个入口。其实还有一种更佳的做法。 ``` >>> 主进程 定义好监听事件 ipc.on('newPage', function(e) { const modalPath = process.env.NODE_ENV === 'development' ? 'http://localhost:9080/#/newPage' : `file://${__dirname}/index.html#newPage` let win = new BrowserWindow({ width: 1024, height: 724, webPreferences: { webSecurity: false } }) win.on('close', function() { win = null }) win.loadURL(modalPath) }) >>> router/index.js 定义路由 // import 你的新页面 .vue 文件 { path: '/newPage', name: 'newPage', component: newPage, } 》》》配置完成 任意进程调用ipc.send('newPage') 完美解决 ``` 3. ``` document.getElementById("youtube").onclick = function(){ youtubeWindow = new BrowserWindow ({width: 1000, height:800}) youtubeWindow.loadURL("https://youtube.com/"); youtubeWindow.on("close", function(){ youtubeWindow = null; }) } document.getElementById("local-list").onclick = function(){ localListWindow = new BrowserWindow ({width: 1000, height:800}) localListWindow.loadURL(`file://${__dirname}/local-list.html`); localListWindow.on("close", function(){ localListWindow = null; }) } ```