├── .gitattributes ├── README.md ├── SUMMARY.md ├── api ├── README.md ├── accelerator.md ├── app.md ├── auto-updater.md ├── browser-view.md ├── browser-window-proxy.md ├── browser-window.md ├── chrome-command-line-switches.md ├── client-request.md ├── clipboard.md ├── content-tracing.md ├── cookies.md ├── crash-reporter.md ├── debugger.md ├── desktop-capturer.md ├── dialog.md ├── download-item.md ├── environment-variables.md ├── file-object.md ├── frameless-window.md ├── global-shortcut.md ├── incoming-message.md ├── ipc-main.md ├── ipc-renderer.md ├── locales.md ├── menu-item.md ├── menu.md ├── native-image.md ├── net.md ├── power-monitor.md ├── power-save-blocker.md ├── process.md ├── protocol.md ├── remote.md ├── sandbox-option.md ├── screen.md ├── session.md ├── shell.md ├── structures │ ├── README.md │ ├── bluetooth-device.md │ ├── certificate-principal.md │ ├── certificate.md │ ├── cookie.md │ ├── cpu-usage.md │ ├── crash-report.md │ ├── desktop-capturer-source.md │ ├── display.md │ ├── file-filter.md │ ├── io-counters.md │ ├── jump-list-category.md │ ├── jump-list-item.md │ ├── memory-info.md │ ├── memory-usage-details.md │ ├── mime-typed-buffer.md │ ├── printer-info.md │ ├── process-memory-info.md │ ├── rectangle.md │ ├── remove-client-certificate.md │ ├── remove-password.md │ ├── scrubber-item.md │ ├── segmented-control-segment.md │ ├── shortcut-details.md │ ├── task.md │ ├── thumbar-button.md │ ├── upload-blob.md │ ├── upload-data.md │ ├── upload-file-system.md │ ├── upload-file.md │ └── upload-raw-data.md ├── synopsis.md ├── system-preferences.md ├── touch-bar-button.md ├── touch-bar-color-picker.md ├── touch-bar-group.md ├── touch-bar-label.md ├── touch-bar-popover.md ├── touch-bar-scrubber.md ├── touch-bar-segmented-control.md ├── touch-bar-slider.md ├── touch-bar-spacer.md ├── touch-bar.md ├── tray.md ├── web-contents.md ├── web-frame.md ├── web-request.md ├── webview-tag.md └── window-open.md ├── demo ├── README.md └── images │ ├── 01.png │ ├── 02.gif │ ├── 03.png │ ├── 04.png │ ├── 05.png │ ├── 06.png │ ├── 07.png │ ├── 08.png │ ├── 09.png │ ├── 10.gif │ ├── now.png │ ├── qq.png │ └── trayWindow.png ├── development ├── README.md ├── build-instructions-linux.md ├── build-instructions-osx.md ├── build-instructions-windows.md ├── build-system-overview.md ├── chromium-development.md ├── clang-format.md ├── coding-style.md ├── debug-instructions-windows.md ├── debugging-instructions-macos.md ├── setting-up-symbol-server.md ├── source-code-directory-structure.md ├── upgrading-chrome.md └── v8-development.md ├── faq.md ├── glossary.md ├── quick-start ├── index.html ├── main.js ├── package.json └── start.bat └── tutorial ├── README.md ├── about.md ├── application-distribution.md ├── application-packaging.md ├── debugging-main-process-node-inspector.md ├── debugging-main-process-vscode.md ├── debugging-main-process.md ├── desktop-environment-integration.md ├── devtools-extension.md ├── electron-versioning.md ├── keyboard-shortcuts.md ├── mac-app-store-submission-guide.md ├── multithreading.md ├── notifications.md ├── offscreen-rendering.md ├── online-offline-events.md ├── planned-breaking-changes.md ├── quick-start.md ├── repl.md ├── security.md ├── supported-platforms.md ├── testing-on-headless-ci.md ├── using-native-node-modules.md ├── using-pepper-flash-plugin.md ├── using-selenium-and-webdriver.md ├── using-widevine-cdm-plugin.md └── windows-store-guide.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /api/README.md: -------------------------------------------------------------------------------- 1 | # API接口目录: 2 | 3 | ## 公用: 4 | * [应用语言](locales.md) 5 | * [开发概要](synopsis.md) 6 | * [专业术语](glossary.md) 7 | * [常见问题](faq.md) 8 | * [环境变量](environment-variables.md) 9 | * [快捷键字符串](accelerator.md) 10 | * [命令行](chrome-command-line-switches.md) 11 | * [客户端请求](client-request.md) 12 | * [剪贴板](clipboard.md) 13 | * [ `` H5 File文件操作](file-object.md) 14 | * [无框窗口](frameless-window.md) 15 | * [ `` window.open打开新窗口或打开时传递消息](window-open.md) 16 | * [沙盒选项](sandbox-option.md) 17 | 18 | ## 主进程: 19 | * [整体控制](app.md) 20 | * [全局快捷键](global-shortcut.md) 21 | * [图标创建与应用](native-image.md) 22 | * [屏幕](screen.md) 23 | * [窗口](browser-window.md) 24 | * [菜单](menu.md) 25 | * [菜单项](menu-item.md) 26 | * [系统托盘](tray.md) 27 | * [网页内容](web-contents.md) 28 | * [从主进程到渲染进程的异步通信](ipc-main.md) 29 | * [对话框](dialog.md) 30 | * [创建和控制视图](browser-view.md) 31 | * [会话](cookies.md) 32 | * [会话,缓存和代理等控制](session.md) 33 | * [页面请求](web-request.md) 34 | * [HTTP/HTTPS请求处理](incoming-message.md) 35 | * [协议的注册和处理](protocol.md) 36 | * [使用系统默认应用程序管理文件或URL](shell.md) 37 | * [下载项管理](download-item.md) 38 | * [进程控制](process.md) 39 | * [Chromium原生网络库](net.md) 40 | * [获取系统首选项](system-preferences.md) 41 | * [电源状态](power-monitor.md) 42 | * [节能管理](power-save-blocker.md) 43 | * [调试工具](debugger.md) 44 | * [奔溃报告](crash-reporter.md) 45 | * [性能数据收集](content-tracing.md) 46 | * [自动更新](auto-updater.md) 47 | * [TouchBar触摸条](touch-bar.md) 48 | * [TouchBar触摸条按钮](touch-bar-button.md) 49 | * [TouchBar触摸条拾色器](touch-bar-color-picker.md) 50 | * [TouchBar触摸条分组](touch-bar-group.md) 51 | * [TouchBar触摸条scrubber](touch-bar-scrubber.md) 52 | * [TouchBar触摸条分段控件](touch-bar-segmented-control.md) 53 | * [TouchBar触摸条label标签](touch-bar-label.md) 54 | * [TouchBar触摸条弹出框](touch-bar-popover.md) 55 | * [TouchBar触摸条滑块](touch-bar-slider.md) 56 | * [TouchBar触摸条间隔符](touch-bar-spacer.md) 57 | 58 | ## 渲染进程: 59 | * [页面渲染](web-frame.md) 60 | * [ `` webview标签](webview-tag.md) 61 | * [渲染进程与主进程通信](remote.md) 62 | * [从渲染进程到主进程的异步通信](ipc-renderer.md) 63 | * [子窗口](browser-window-proxy.md) 64 | * [捕获桌面资源](desktop-capturer.md) -------------------------------------------------------------------------------- /api/accelerator.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:快捷键字符串 2 | 3 | >使用[`globalShortcut`](global-shortcut.md)中的[`register`](global-shortcut.md#globalshortcutregisteraccelerator-callback)绑定快捷键. 4 | 5 | # 快捷键字符串 6 | 7 | 多个则采用 `+` 连接,例如: 8 | * `CommandOrControl+A` 9 | * `CommandOrControl+Shift+Z` 10 | 11 | 例子: 12 | 13 | ```JavaScript 14 | const {app, globalShortcut} = require('electron') 15 | 16 | app.on('ready', () => { 17 | // 注册 'CommandOrControl+Y' 快捷方式监听器 18 | globalShortcut.register('CommandOrControl+Y', () => { 19 | // 按下 Y + either Command/Control后的处理 20 | }) 21 | }) 22 | ``` 23 | 24 | ## 可用的功能键 25 | 26 | * `Command`(或缩写为 `Cmd`) 27 | * `Control`(或缩写为 `Ctrl`) 28 | * `CommandOrControl`(或缩写为 `CmdOrCtrl`) - Linux 和 Windows 下的 `Control` 键,macOS 的 `Command` 键。 29 | * `Alt` 30 | * `Option` 31 | * `AltGr` 32 | * `Shift` 33 | * `Super` - Linux 和 Windows 上的 `Windows` 键,macOS 的 `Command` 键。 34 | 35 | ## 可用的普通键 36 | 37 | * `0` 到 `9` 38 | * `A` 到 `Z` 39 | * `F1` 到 `F12` 40 | * 类似 `~`, `!`, `@`, `#`, `$` 的标点符号。 41 | * `Plus` 42 | * `Space` 43 | * `Backspace` 44 | * `Delete` 45 | * `Insert` 46 | * `Return`(等同 `Enter` ) 47 | * `Up`, `Down`, `Left` 和 `Right` 48 | * `Home` 和 `End` 49 | * `PageUp` 和 `PageDown` 50 | * `Escape`(可缩写为 `Esc`) 51 | * `VolumeUp` , `VolumeDown` 和 `VolumeMute` 52 | * `MediaNextTrack` , `MediaPreviousTrack` , `MediaStop` 和 `MediaPlayPause` 53 | * `PrintScreen` 54 | -------------------------------------------------------------------------------- /api/auto-updater.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:自动更新应用 2 | > `autoUpdater`模块为[Squirrel](https://github.com/Squirrel)框架提供了一个接口。 3 | 4 | 进程: [主进程](../glossary.md#主进程) 5 | 6 | 您可以使用这些项目之一进行快速启动多平台发布服务器以分发应用程序: 7 | - [nuts][nuts]:*为您的应用程序使用智能版本服务器,使用GitHub作为后端。使用Squirrel(Mac和Windows)自动更新* 8 | - [electron-release-server][electron-release-server]:*功能齐全,自主托管的electron应用程序的发布服务器,兼容自动更新器* 9 | - [squirrel-updates-server][squirrel-updates-server]:*简单的node.js服务器为Squirrel.Mac和Squirrel.Windows使用GitHub版本* 10 | - [squirrel-release-server][squirrel-release-server]:*简单的Squirrel.Windows的PHP应用程序,它从文件夹读取更新。支持增量更新。* 11 | 12 | ## 平台相关的提示 13 | 14 | 虽然 `autoUpdater` 模块提供了一套各平台通用的接口,但是在每个平台间依然会有一些微小的差异。 15 | 16 | ### macOS 17 | 18 | 在macOS上,`autoUpdater`模块建立在[Squirrel.Mac][squirrel-mac]上,这意味着你不需要任何特殊的设置来使它工作。 19 | 20 | 对于服务器端要求,您可以阅读 [Server Support][server-support]. 21 | 22 | 注意[App传输安全](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35)(ATS)适用于所有请求作为更新过程的一部分。 23 | 24 | 如需禁用ATS的应用程序可以在其应用程序的plist中添加 `NSAllowsArbitraryLoads`键。 25 | 26 | **注意:**您的应用程序必须在macOS上进行自动更新。这是[Squirrel.Mac][squirrel-mac]的要求。 27 | 28 | ### Windows 29 | 30 | 在 Windows 上,你必须使用安装程序将你的应用装到用户的计算机上,所以比较推荐的方法是用 [electron-winstaller][installer-lib], [electron-builder][electron-builder-lib] 或 [grunt-electron-installer][installer] 模块来生成Windows安装程序。 31 | 32 | 当使用[electron-winstaller][installer-lib]或[electron-winstaller][installer-lib], [electron-builder][electron-builder-lib]时,确保你不要尝试更新你的应用程序[第一次运行](https://github.com/electron/windows-installer#handling-squirrel-events)(另见[这个问题的更多信息](https://github.com/electron/electron/issues/7155))。还建议使用[electron-squirrel-startup](https://github.com/mongodb-js/electron-squirrel-startup)获取应用程序的桌面快捷方式。 33 | 34 | 使用Squirrel生成的安装程序将以 `com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`的格式创建一个带有[Application User Model ID][app-user-model-id]的快捷图标,例子是 `com.squirrel.slack.Slack'和 `com.squirrel.code.Code`。 35 | 36 | 您应确保程序具有 `app.setAppUserModelId` API且ID相同,否则Windows将无法在应用程式的工作列中正确匹配您的应用程序。 37 | 38 | 服务器端设置也不同于macOS。您可以阅读[Squirrel.Windows][squirrel-windows]的文档以获得更多详细信息。 39 | 40 | ### Linux 41 | 42 | 在Linux上没有自动更新器的内置支持,因此建议使用分发包的包管理器来更新您的应用程序。 43 | 44 | ## 事件列表 45 | 46 | `autoUpdater` 对象会触发以下的事件: 47 | 48 | ### 事件:'error' 49 | > 触发:**更新发生错误时** 50 | 51 | * `error` Error 52 | 53 | ### 事件:'checking-for-update' 54 | > 触发:**开始检查更新时** 55 | 56 | ### 事件:'update-available' 57 | > 触发:**发现一个可用更新时** 58 | 59 | ### 事件:'update-not-available' 60 | > 触发:**没有可用更新时** 61 | 62 | ### 事件:'update-downloaded' 63 | > 触发:**更新下载完成时** 64 | 65 | * `event` Event 66 | * `releaseNotes` String - 新版本更新公告 67 | * `releaseName` String - 新的版本号 68 | * `releaseDate` Date - 新版本发布的日期 69 | * `updateURL` String - 更新地址 70 | 71 | 在 Windows 上只有 `releaseName` 是有效的。 72 | 73 | ## 方法列表 74 | 75 | `autoUpdater` 对象有以下的方法: 76 | 77 | ### `autoUpdater.setFeedURL(url)` 78 | > 用途:**设置 `url`并初始化自动更新器** 79 | 80 | * `url` String 81 | * `requestHeaders` Object _macOS_ (可选) - HTTP请求标头. 82 | 83 | ### `autoUpdater.getFeedURL()` 84 | > 用途:**获得当前更新的Feed链接** 85 | 86 | 返回 `String` 87 | 88 | ### `autoUpdater.checkForUpdates()` 89 | > 用途:**询问服务器是否有更新** 90 | 91 | 在调用这个方法之前,必须要先调用 `setFeedURL`。 92 | 93 | ### `autoUpdater.quitAndInstall()` 94 | > 用途:**重新启动应用程序,并在更新已下载后安装** 95 | 96 | 该方法只有在 `update-downloaded`被释放后才被调用。 97 | 98 | **注意项:** `autoUpdater.quitAndInstall()`和普通退出有所区别,它将先关闭所有应用程序窗口,然后在 `app`上发出 `before-quit`事件。 99 | 100 | [squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac 101 | [server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support 102 | [squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows 103 | [installer]: https://github.com/electron/grunt-electron-installer 104 | [installer-lib]: https://github.com/electron/windows-installer 105 | [electron-builder-lib]: https://github.com/electron-userland/electron-builder 106 | [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx 107 | [electron-release-server]: https://github.com/ArekSredzki/electron-release-server 108 | [squirrel-updates-server]: https://github.com/Aluxian/squirrel-updates-server 109 | [nuts]: https://github.com/GitbookIO/nuts 110 | [squirrel-release-server]: https://github.com/Arcath/squirrel-release-server -------------------------------------------------------------------------------- /api/browser-view.md: -------------------------------------------------------------------------------- 1 | ## 类: BrowserView 2 | 3 | > 创建和控制视图 4 | 5 | **注意:** BrowserView API目前为实验性质,可能会更改或删除。 6 | 7 | 进程:[主进程](../glossary.md#主进程) 8 | 9 | `BrowserView`是 `webview`的替代标签,就像是子窗口一样让某个 `BrowserWindow`嵌入更多的Web内容. 10 | 11 | ## 例子 12 | 13 | ```javascript 14 | // 主进程中 15 | const {BrowserView, BrowserWindow} = require('electron') 16 | 17 | let win = new BrowserWindow({width: 800, height: 600}) 18 | win.on('closed', () => { 19 | win = null 20 | }) 21 | 22 | let view = new BrowserView() 23 | win.setBrowserView(view) 24 | view.setBounds({ x: 0, y: 0, width: 300, height: 300 }) 25 | view.webContents.loadURL('https://electron.atom.io') 26 | ``` 27 | 28 | ### `new BrowserView([options])` _实验功能_ 29 | 30 | * `options` Object (可选) 31 | * `webPreferences` Object (可选) - 详细查看 [BrowserWindow](browser-window.md). 32 | 33 | ### 实例属性 34 | 35 | 使用 `new BrowserView`创建的对象具有以下属性: 36 | 37 | #### `view.webContents` _实验功能_ 38 | > 属性:**视图的[`WebContents`](web-contents.md)对象** 39 | 40 | #### `view.id` _实验功能_ 41 | > 属性:**视图的唯一ID( `Integer`)** 42 | 43 | ### 实例方法 44 | 45 | 使用 `new BrowserWindow` 创建的对象具有以下实例方法: 46 | 47 | 48 | #### `view.setAutoResize(options)` _实验功能_ 49 | > 用途:**调整视图大小时设置视图尺寸跟随变化** 50 | 51 | * `options` Object 52 | * `width` Boolean - `true`即视图宽度跟随窗口变化. 默认为 `false`. 53 | * `height` Boolean - `true`即视图高度跟随窗口变化. 默认为 `false`. 54 | 55 | #### `view.setBounds(bounds)` _实验功能_ 56 | > 用途:**调整视图大小并将它移动至窗口边界** 57 | 58 | * `bounds` [Rectangle](structures/rectangle.md) 59 | 60 | #### `view.setBackgroundColor(color)` _实验功能_ 61 | > 用途:**设置视图的背景颜色** 62 | 63 | * `color` String - 颜色值格式如 `#aarrggbb` 或 `#argb`,可选透明度. -------------------------------------------------------------------------------- /api/browser-window-proxy.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:BrowserWindowProxy类(子窗口的控制与应用) 2 | 3 | >操纵子窗口 4 | 5 | 进程:[渲染进程](../glossary.md#渲染进程) 6 | 7 | 使用 `window.open` 创建一个新窗口时,会自动创建一个 `BrowserWindowProxy` 的实例将返回一个标识,可通过标识对这个新窗口进行少量功能的控制. 8 | 9 | ## 实例方法 10 | 11 | `BrowserWindowProxy`对象具有以下实例方法: 12 | 13 | ### `win.blur()` 14 | > 用途:**从子窗口中去焦** 15 | 16 | ### `win.close()` 17 | > 用途:**强制关闭子窗口,而不调用其卸载事件(unload event)** 18 | 19 | ### `win.eval(code)` 20 | > 用途:**eval子窗口中的代码** 21 | 22 | * `code`String 23 | 24 | ### `win.focus()` 25 | > 用途:**聚焦子窗口(即窗口置顶)** 26 | 27 | ### `win.print()` 28 | > 用途:**调用子窗口上的打印对话框** 29 | 30 | ### `win.postMessage(message,targetOrigin)` 31 | > 用途:**调通过指定位置 或 用 `*` 来代替不明位置 向父窗口发送信息** 32 | * `message` String 33 | * `targetOrigin` String 34 | 35 | 除了这些方法,子窗口还可以无特性和使用单一方法来实现 `window.opener` 对象. 36 | 37 | ## 实例属性 38 | `BrowserWindowProxy`对象具有以下实例属性: 39 | 40 | ### `win.closed` 41 | > 用途:**关闭子窗口后恢复为 `true`** -------------------------------------------------------------------------------- /api/chrome-command-line-switches.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:支持的 Chrome 命令行开关 2 | 3 | >下文列出了Chrome浏览器和Electron支持的命令行开关. 4 | 5 | 你也可以在[app][app]模块的[ready][ready]事件之前使用[app.commandLine.appendSwitch][append-switch] 来添加它们到你应用的main脚本里面: 6 | ```javascript 7 | const {app} = require('electron') 8 | app.commandLine.appendSwitch('remote-debugging-port','8315') 9 | app.commandLine.appendSwitch('host-rules','MAP * 127.0.0.1') 10 | 11 | app.on('ready',()=> { 12 | //您的代码在这里 13 | }) 14 | ``` 15 | 16 | ## --ignore-connections-limit =`domains` 17 | 18 | 忽略由 `,`分隔的 `domains`列表的连接数限制。 19 | 20 | ## --disable-http-cache 21 | 22 | 为HTTP请求禁用磁盘缓存。 23 | 24 | ## --disable-http2 25 | 26 | 禁用HTTP/2和SPDY/3.1协议。 27 | 28 | ## --inspect =`port`和--inspect-brk =`port` 29 | 30 | 调试相关标志,详见[调试主进程][debugging-main-process] 31 | 32 | ## --remote-debugging-port =`port` 33 | 34 | 通过HTTP在指定的端口上启用远程调试。 35 | 36 | ## --js-flags =`flags' 37 | 38 | 指定引擎过渡到 JS 引擎. 39 | 40 | 在启动Electron时,如果你想在主进程中激活 `flags` ,它将被转换. 41 | 42 | ```bash 43 | $ electron --js-flags =` - harmony_proxies --harmony_collections`your-app 44 | ``` 45 | 46 | 请参阅[Node文档][node-cli]或在终端中运行`node --help`以获取可用标志列表。 47 | 48 | 另外,运行`node --v8-options`可以看到特定引用Node的V8 JavaScript引擎的标志列表。 49 | 50 | ## --proxy-server =`address:port` 51 | 52 | 使用指定的代理服务器,该服务器覆盖系统设置。这个开关仅影响具有HTTP协议的请求,包括HTTPS和WebSocket要求。还值得注意的是,并非所有代理服务器都支持HTTPS和WebSocket请求。 53 | 54 | ## --proxy-bypass-list =`hosts` 55 | 56 | 指示Electron绕过给定分号分隔的代理服务器主机列表。此标志只有与 `--proxy-server`串联使用时才有效果 。 57 | 58 | 例如: 59 | 60 | ```javascript 61 | const {app} = require('electron') 62 | app.commandLine.appendSwitch('proxy-bypass-list','; *。google.com; * foo.com; 1.2.3.4:5678') 63 | ``` 64 | 65 | 将为所有主机使用代理服务器,除了本地地址( `localhost`, `127.0.0.1`等), `google.com`子域,包含后缀 `foo.com`的主机和 `1.2.3.4 :5678`。 66 | 67 | ## --proxy-pac-url =`url` 68 | 69 | 在指定的`url`使用PAC脚本。 70 | 71 | ## --no-proxy-server 72 | 73 | 不要使用代理服务器并始终进行直接连接。覆盖传递的任何其他代理服务器标志。 74 | 75 | ## --host-rules =`rules` 76 | 77 | 以逗号分隔的`rules`列表,用于控制主机名的映射方式。 78 | 79 | 例如: 80 | 81 | * `MAP * 127.0.0.1`强制所有主机名映射到127.0.0.1 82 | * `MAP * .google.com proxy`强制将所有google.com子域解析为 `proxy`。 83 | * `MAP test.com [:: 1]:77`强制 `test.com`解决IPv6环回。 也将强制端口的所得套接字地址为77。 84 | * `MAP * baz,EXCLUDE www.google.com`将所有内容重新映射到`baz`,除了`www.google.com`。 85 | 86 | 这些映射适用于网络请求(TCP连接)中的端点主机和主机解析器在一个直接连接,和`CONNECT`在HTTP代理连接,以及SOCKS代理连接中的端点主机)。 87 | 88 | ## --host-resolver-rules =`rules` 89 | 90 | 像`--host-rules`,但这些规则只适用于主机解析器。 91 | 92 | ## --auth-server-whitelist =`url` 93 | 94 | 启用集成身份验证的服务器的逗号分隔列表。 95 | 96 | 例如: 97 | 98 | ```bash 99 | --auth-server-whitelist ='* example.com,* foobar.com,* baz' 100 | ``` 101 | 102 | 那么以`example.com`,`foobar.com`,`baz`结尾的任何 `ur`将被考虑用于集成认证。如果没有 `*`前缀, `url`必须完全匹配。 103 | 104 | ## --auth-negotiate-delegate-whitelist =`url` 105 | 106 | 需要委派用户凭据的服务器的逗号分隔列表。如果没有 `*`前缀,url必须完全匹配。 107 | 108 | ## --ignore-certificate-errors 109 | 110 | 忽略与证书相关的错误。 111 | 112 | ## --ppapi-flash-path =`path` 113 | 114 | 设置ppapi flash插件的`path`。 115 | 116 | ## --ppapi-flash-version =`version` 117 | 118 | 设置ppapi flash插件的版本。 119 | 120 | ## --log-net-log =`path` 121 | 122 | 允许保存网络日志事件,并将其写入`path`。 123 | 124 | ## --ssl-version-fallback-min =`version` 125 | 126 | 设置TLS的最低SSL/TLS版本(`tls1`,`tls1.1`或`tls1.2`) 127 | 128 | 回退会接受。 129 | 130 | ## --cipher-suite-blacklist =`cipher_suites` 131 | 132 | 指定要禁用的SSL密码套件的逗号分隔列表。 133 | 134 | ## --disable-renderer-backgrounding 135 | 136 | 防止 Chromium 降低隐藏的渲染进程优先级. 137 | 138 | 这个标志对所有渲染进程全局有效,如果你只想在一个窗口中禁止使用,你可以采用 hack 方法[playing silent audio][play-silent-audio]. 139 | 140 | ## --enable-logging 141 | 142 | 打印 Chromium 信息输出到控制台. 143 | 144 | 此开关不能在 `app.commandLine.appendSwitch`中使用,因为它在用户的应用程序加载之前被解析,但是您可以设置 `ELECTRON_ENABLE_LOGGING` 环境变量以实现相同的效果。 145 | 146 | ## --v =`log_level` 147 | 148 | 提供默认最大活动V日志记录级别; 0是默认值。通常正值用于V日志级别。 149 | 150 | 此开关仅在 `--enable-logging`也通过时才起作用。 151 | 152 | ## --vmodule =`pattern` 153 | 154 | 给出每个模块的最大V日志记录级别以覆盖`--v'给定的值。例如。 `my_module = 2,foo * = 3`将改变源文件`my_module。*`和`foo *。*`中所有代码的日志记录级别。 155 | 156 | 任何包含前向或反向斜线的模式都将针对整个路径名而不仅仅是模块进行测试。例如。 `*/foo/bar/* = 2`将会改变`foo/bar`目录下源文件中所有代码的日志级别。 157 | 158 | 此开关仅在`--enable-logging`也通过时才起作用。 -------------------------------------------------------------------------------- /api/client-request.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:ClientRequest类 2 | >客户端的HTTP/HTTPS请求。 3 | 4 | 进程:[主进程](../glossary.md#主进程) 5 | 6 | `ClientRequest`是由[EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)来实现[Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams) 7 | 8 | ### `new ClientRequest(options)` 9 | > 作用:**发起新的HTTP/HTTPS请求** 10 | 11 | * `options`(Object | String) - `options`是String时即请求URL。 `options` 是Object时则按以下属性请求: 12 | * `method` String(可选) - HTTP请求方法。默认为 `GET`。 13 | * `url` String(可选) - 请求URL。协议为http或https。 14 | * `session` Object(可选) - [`Session`](session.md)与请求相关联。 `session` 优先于 `partition`。 15 | * `partition` String(可选) - [`partition`]的名称[`partition`](session.md)与请求相关联。默认为空字符串。如果 `session`是显式的指定, `partition`被忽略。 16 | * `protocol` String(可选) - `scheme:`形式的协议方案。可选 `http:`或 `https:`。默认为 `http:`。 17 | * `host` String(可选) - 作为连接提供的服务器主机,主机名和端口号`hostname:port` 18 | * `hostname` String(可选) - 服务器主机名。 19 | * `port` Integer(可选) - 服务器的侦听端口号。 20 | * `path` String(可选) - 请求URL的路径部分。 21 | * `redirect` String(可选) - 请求的重定向模式。可选值 `follow`(跟随) , `error`(错误)或 `manual`(手动),默认为 `follow`。 `error`表示任何重定向将被中止。 `manual` 表示延迟重定向直到调用了[`request.followRedirect`](#requestfollowRedirect)。有关重定向请求的更多细节请查看[`redirect`](#event-redirect)事件。 22 | 23 | 24 | `options`属性,如 `protocol`, `host`, `hostname`, `port`和 `path`严格遵循Node.js模型,如[URL](https://nodejs.org/api/url.html)模块。 25 | 26 | 例如,我们可以创建与`github.com`相同的请求如下: 27 | 28 | ```JavaScript 29 | const request = net.request({ 30 | method:'GET', 31 | protocol:'https:', 32 | hostname:'github.com', 33 | port:443, 34 | path:'/' 35 | }) 36 | ``` 37 | 38 | ### 实例事件 39 | 40 | #### 事件:'response' 41 | > 触发:**HTTP响应消息对象时** 42 | 43 | * `response` (IncomingMessage) 44 | 45 | #### 事件:'login' 46 | > 触发:**认证代理请求用户凭据时** 47 | 48 | * `authInfo`对象 49 | * `isProxy` Boolean 50 | * `scheme` String 51 | * `host` String 52 | * `port` Integer 53 | * `realm` String 54 | * `callback` Function 发起凭据并用`callback`回调 55 | * `username` String 56 | * `password` String 57 | 58 | ```JavaScript 59 | request.on('login',(authInfo,callback)=> { 60 | callback('username','password') 61 | }) 62 | ``` 63 | 提供空凭证将取消请求并在响应对象上报告认证错误: 64 | ```JavaScript 65 | request.on('response',(response)=> { 66 | console.log(`STATUS:${response.statusCode}`); 67 | response.on('error',(error)=> { 68 | console.log(`ERROR:${JSON.stringify(error)}`) 69 | }) 70 | }) 71 | request.on('login',(authInfo,callback)=> { 72 | callback() 73 | }) 74 | ``` 75 | 76 | #### 事件:'finish' 77 | > 触发:**请求完成时** 78 | 79 | #### 事件:'abort' 80 | > 触发:**请求中止时** 81 | 82 | 如果 `request`已经关闭, `abort`事件不会被触发。 83 | 84 | #### 事件:'error' 85 | > 触发:**请求错误时** 86 | 87 | * `error` Error - 包含失败原因的一个对象。 88 | 89 | `net`模块无法发出网络请求时触发。通常在 `request`对象发出一个 `error`事件,一个 `close`事件随后 90 | 跟随并且不提供响应对象。 91 | 92 | #### 事件:'close' 93 | > 触发:**请求关闭时** 94 | 95 | 作为HTTP请求 - 响应事务中的最后一个事件。 `close`事件表示不再发出 `request`或者`response`对象。 96 | 97 | #### 事件: 'redirect' 98 | > 触发:**发起模式为 `manual`(手动)的重定向时** 99 | * `statusCode` Integer 100 | * `method` String 101 | * `redirectUrl` String 102 | * `responseHeaders` Object 103 | 104 | 使用[`request.followRedirect`](#requestfollowRedirect)可继续重定向. 105 | 106 | ### 实例属性 107 | 108 | #### `request.chunkedEncoding` 109 | 指定请求是否将使用HTTP分块传输编码的布尔值。默认为 `false` 110 | 111 | 该属性是可读写的,但它可以只在第一次写操作之前设置,在第一次写入后设置 `chunkedEncoding`属性后会抛出一个错误。 112 | 113 | 如果请求较大且复杂时,使用分块可有效提高效率.因为数据将以小块形式流传输,而不是在Electron进程内存中内部缓冲。 114 | 115 | 116 | ### 实例方法 117 | 118 | #### `request.setHeader(name,value)` 119 | > 用途:**设置HTTP头** 120 | 121 | * `name` String - 额外的HTTP头名称。 122 | * `value` String - 额外的HTTP头值。 123 | 124 | 必须注意的是,它只能在第一次写入前调用。在第一次写入后调用此方法将抛出一个错误。 125 | 126 | #### `request.getHeader(name)` 127 | > 用途:**获取HTTP头** 128 | 129 | * `name` String - 指定的额外标题名称。 130 | 返回String - 以前设置的额外头名称的值。 131 | 132 | #### `request.removeHeader(name)` 133 | > 用途:**删除先前设置的HTTP头** 134 | 135 | * `name` String - 指定的额外标题名称。 136 | 137 | 必须注意的是,它只能在第一次写入前调用。在第一次写入后调用此方法将抛出一个错误。 138 | 139 | #### `request.write(chunk [,encoding] [,callback])` 140 | > 用途:**写入新的请求并等待响应** 141 | 142 | * `chunk`(String | Buffer) - 请求主体数据的一个块。如果是字符串,它将使用指定的编码转换为Buffer。 143 | * `encoding` String(可选) - 用于将字符串块转换为Buffer对象。默认为 `utf-8`。 144 | * `callback` Function(可选) - 在写操作结束后调用。 145 | 146 | `callback`本质上是为了保持与Node.js API的相似性而引入的虚拟函数。 147 | 148 | 在chunk的内容传递到Chromium网络层后,在下一个tick中被异步调用。与Node.js实现相反,不能保证 `chunk`内容在调用 `callback`之前已经被刷新了块内容. 149 | 150 | 向请求正文中添加一个数据块。 151 | 152 | 第一次写操作可能导致在线路上发出请求头。 153 | 154 | 第一次写操作后,不允许添加或删除自定义标题。 155 | 156 | #### `request.end([chunk] [,encoding] [,callback])` 157 | > 用途:**发送请求数据的最后一个块。将不允许后续写入或结束操作** 158 | 159 | * `chunk`(String | Buffer)(可选) 160 | * `encoding` String(可选) 161 | * `callback`函数(可选) 162 | 163 | `finish`事件是在结束操作之后发出的。 164 | 165 | #### `request.abort()` 166 | > 用途:**取消正在进行的HTTP事务** 167 | 168 | 如果请求已经发出了 `close`事件,中止操作将无效。否则正在进行的事件将触发 `abort`和 `close`事件。 169 | 170 | 另外,如果有正在进行的响应对象,它将发出 `aborted`事件。 171 | 172 | #### `request.followRedirect()` 173 | > 用途:**重定向模式为 `manual`(手动)时,继续延迟重定向请求** -------------------------------------------------------------------------------- /api/clipboard.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:剪贴板操作 2 | >在系统剪贴板上执行复制和剪贴操作 3 | 4 | 进程: [主进程](../glossary.md#主进程), [渲染进程](../glossary.md#渲染进程) 5 | 6 | 复制字符串例子: 7 | ```JavaScript 8 | const {clipboard} = require('electron') 9 | clipboard.writeText('Example String') 10 | ``` 11 | 在X Window系统上,还有一个选择剪贴板。要操作它,你需要传递`selection`到每个方法: 12 | ```JavaScript 13 | const {clipboard} = require('electron') 14 | clipboard.writeText('Example String', 'selection') 15 | console.log(clipboard.readText('selection')) 16 | ``` 17 | 18 | ## 方法 19 | `clipboard` 模块有以下方法: 20 | 21 | ### `clipboard.readText([type])` 22 | > 用途:**读取剪贴文本** 23 | 24 | * `type` String (可选) 25 | 26 | ### `clipboard.writeText(text[, type])` 27 | > 用途:**将文本添加到剪贴板** 28 | 29 | * `text` String 30 | * `type` String (可选) 31 | 32 | ### `clipboard.readHTML([type])` 33 | > 用途:**读取剪贴板中的 `markup` 内容** 34 | 35 | * `type` String (可选) 36 | 37 | ### `clipboard.writeHTML(markup[, type])` 38 | > 用途:**向剪贴板中添加 `markup` 内容** 39 | 40 | * `markup` String 41 | * `type` String (可选) 42 | 43 | ### `clipboard.readImage([type])` 44 | > 用途:**读取剪贴板中的`[NativeImage](native-image.md)` 内容** 45 | 46 | * `type` String (可选) 47 | 48 | ### `clipboard.writeImage(image[, type])` 49 | > 用途:**向剪贴板中添加`[NativeImage](native-image.md)` 内容** 50 | 51 | * `image` [NativeImage](native-image.md) 52 | * `type` String (可选) 53 | 54 | ### `clipboard.readRTF([type])` 55 | > 用途:**读取剪贴板中的`RTF` 内容** 56 | 57 | * `type` String (可选) 58 | 59 | ### `clipboard.writeRTF(text[, type])` 60 | > 用途:**向剪贴板中添加 `RTF` 内容** 61 | 62 | * `text` String 63 | * `type` String (可选) 64 | 65 | ### `clipboard.readBookmark()` _macOS_ _Windows_ 66 | > 用途:**读取剪贴板中的包含表示书签的 `title` 和 `url` 键的对象** 67 | 68 | * `title` String 69 | * `url` String 70 | 71 | 如果书签不可用, `title'和 `url`值将是空字符串 72 | 73 | ### `clipboard.writeBookmark(title, url[, type])` _macOS_ _Windows_ 74 | > 用途:**向剪贴板中添加表示书签的 `title` 和 `url` 键的对象** 75 | 76 | * `title` String 77 | * `url` String 78 | * `type` String (可选) 79 | 80 | **注意:** 大部分WIN程序都不支持直接复制或剪贴书签,你可以使用 `clipboard.write`来写入. 81 | 82 | ```JavaScript 83 | clipboard.write({ 84 | text: 'http://electron.atom.io', 85 | bookmark: 'Electron Homepage' 86 | }) 87 | ``` 88 | 89 | ### `clipboard.readFindText()` _macOS_ 90 | > 用途:**从剪贴板中查找文本** 91 | 92 | 在渲染进程中使用IPC调用该方法进行查找时,每当程序被激活,缓存文本都将被重读. 93 | 94 | ### `clipboard.writeFindText(text)` _macOS_ 95 | > 用途:**以文本形式写入剪贴板** 96 | 97 | * `text` String 98 | 99 | 此方法在从渲染器进程调用时使用同步IPC。 100 | 101 | ### `clipboard.clear([type])` 102 | > 用途:**清除剪贴板内容** 103 | 104 | * `type` String (可选) 105 | 106 | ### `clipboard.availableFormats([type])` 107 | > 用途:**返回剪贴板 `type`支持的格式数组** 108 | 109 | * `type` String (可选) 110 | 111 | ### `clipboard.has(format[, type])` _实验功能_ 112 | > 用途:**判断剪剪贴板是否支持指定 `format`的格式( `Boolean`)** 113 | 114 | * `format` String 115 | * `type` String (可选) 116 | 117 | ```JavaScript 118 | const {clipboard} = require('electron') 119 | console.log(clipboard.has('

selection

')) 120 | ``` 121 | 122 | ### `clipboard.read(format)` _实验功能_ 123 | > 用途:**从剪贴板读取 `format`格式内容( `String`)** 124 | 125 | * `format` String 126 | 127 | ### `clipboard.readBuffer(format)` _实验功能_ 128 | > 用途:**以输入流形式从剪贴板读取 `format`格式内容( `Buffer`)** 129 | 130 | * `format` String 131 | 132 | ### `clipboard.write(data[, type])` 133 | > 用途:**向剪贴板中添加 `data`** 134 | 135 | * `data` Object 136 | * `text` String (可选) 137 | * `html` String (可选) 138 | * `image` [NativeImage](native-image.md) (可选) 139 | * `rtf` String (可选) 140 | * `bookmark` String (可选) - `text` 里url链接的标题. 141 | * `type` String (可选) 142 | 143 | ```JavaScript 144 | const {clipboard} = require('electron') 145 | clipboard.write({text: 'test', html: 'test'}) 146 | ``` -------------------------------------------------------------------------------- /api/content-tracing.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:contentTracing类 2 | >从Chromium的内容模块收集跟踪数据,以发现性能瓶颈和缓慢的操作 3 | 4 | 进程: [主进程](../glossary.md#主进程) 5 | 6 | 这个模块不具备web接口,需要我们在chrome浏览器中添加 `chrome://tracing/` 来加载生成结果文件. 7 | 8 | 注意该模块应当在 `ready`事件之后使用. 9 | 10 | ```JavaScript 11 | const {contentTracing} = require('electron') 12 | const options = { 13 | categoryFilter: '*', 14 | traceOptions: 'record-until-full,enable-sampling' 15 | } 16 | contentTracing.startRecording(options, () => { 17 | console.log('Tracing started') 18 | 19 | setTimeout(() => { 20 | contentTracing.stopRecording('', (path) => { 21 | console.log('Tracing data recorded to ' + path) 22 | }) 23 | }, 5000) 24 | }) 25 | ``` 26 | ## 方法 27 | 28 | ### `contentTracing.getCategories(callback)` 29 | > 用途:**获取一组类别组,而且类别组可以随着到达新的代码路径而改变** 30 | 31 | * `callback` Function 32 | * `categories` String[] 33 | 34 | 一旦所有的子进程都接受到了 `getCategories`方法请求, 则调用 `callback`返回类别组. 35 | 36 | ### `contentTracing.startRecording(options, callback)` 37 | > 用途:**在所有进程上开始记录** 38 | 39 | * `options` Object 40 | * `categoryFilter` String 41 | * `traceOptions` String 42 | * `callback` Function 43 | 44 | 一旦子进程接收到 `EnableRecording`请求,将立即以异步开始记录。 45 | 46 | 一旦所有子进程都确认了 `startRecording`请求, `callback`将被调用。 47 | 48 | `categoryFilter`是一个过滤器,用于控制应跟踪哪些类别组。 49 | 50 | 过滤器可以具有可选的 `-`前缀,以排除包含匹配类别的类别组。不支持在同一列表中包括和排除类别模式。 51 | 52 | 比如: 53 | * `test_MyTest*`, 54 | * `test_MyTest*,test_OtherStuff`, 55 | * `"-excluded_category1,-excluded_category2` 56 | 57 | `traceOptions` 控制着哪种跟踪应该被启动,这是一个用逗号分隔的列表.可用参数如下: 58 | 59 | * `record-until-full` 60 | * `record-continuously` 61 | * `trace-to-console` 62 | * `enable-sampling` 63 | * `enable-systrace` 64 | 65 | 前3个参数是来跟踪记录模块,并且是互斥关系. 66 | 67 | 如果在 `traceOptions` 中超过一个跟踪记录模式,那最后一个的优先级最高. 68 | 69 | 如果没有指明跟踪记录模式,那么它默认为 `record-until-full`. 70 | 71 | 在 `traceOptions` 中的参数被解析应用之前,跟踪参数会被初始化为默认参数 ( `record_mode` 设置为 `record-until-full`, `enable_sampling` 和 `enable_systrace` 设置为 `false`). 72 | 73 | ### `contentTracing.stopRecording(resultFilePath, callback)` 74 | > 用途:**停止对所有子进程的记录** 75 | 76 | * `resultFilePath` String 77 | * `callback` Function 78 | * `resultFilePath` String 79 | 80 | 子进程通常缓存跟踪数据,并且仅仅将数据截取和发送给主进程. 81 | 82 | 这有利于在通过 IPC 发送跟踪数据之前减小跟踪时的运行开销,这样做很有价值. 83 | 84 | 因此,发送跟踪数据,我们应当异步通知所有子进程来截取任何待跟踪的数据. 85 | 86 | 一旦所有子进程接收到了 `stopRecording` 请求,将调用 `callback` ,并且返回一个包含跟踪数据的文件. 87 | 88 | 如果 `resultFilePath` 不为空,那么将把跟踪数据写入其中,否则写入一个临时文件.实际文件路径如果不为空,则将调用 `callback` . 89 | 90 | ### `contentTracing.startMonitoring(options, callback)` 91 | > 用途:**开始监视所有进程** 92 | 93 | * `options` Object 94 | * `categoryFilter` String 95 | * `traceOptions` String 96 | * `callback` Function 97 | 98 | 一旦子进程接收到 `startMonitoring`请求,将立即以异步开始监听。 99 | 100 | 一旦所有子进程都确认了 `startRecording`请求, `callback`将被调用。 101 | 102 | ### `contentTracing.stopMonitoring(callback)` 103 | > 用途:**停止对所有子进程的监听** 104 | 105 | * `callback` Function 106 | 107 | 一旦所有子进程接收到了 `stopMonitoring` 请求, `callback`将被调用。 108 | 109 | ### `contentTracing.captureMonitoringSnapshot(resultFilePath, callback)` 110 | > 用途:**获取当前监听的跟踪数据** 111 | 112 | * `resultFilePath` String 113 | * `callback` Function 114 | * `resultFilePath` String 115 | 116 | 子进程通常缓存跟踪数据,并且仅仅将数据截取和发送给主进程. 117 | 118 | 因为如果直接通过 IPC 来发送跟踪数据的代价昂贵,我们应当避免不必要的跟踪运行开销. 119 | 120 | 因此,为了停止跟踪,我们可以通过异步通知所有子进程来刷新任何挂起的跟踪数据。 121 | 122 | 一旦所有子进程接收到了 `captureMonitoringSnapshot` 请求,将调用 `callback` ,并且返回一个包含跟踪数据的文件. 123 | 124 | ### `contentTracing.getTraceBufferUsage(callback)` 125 | > 用途:**获取当前监听的跟踪数据** 126 | 127 | * `callback` Function 128 | * `value` Number 129 | * `percentage` Number 130 | 131 | 获取跟踪缓冲区进程的最大使用量与完整状态的百分比。当TraceBufferUsage值被确定时,就调用 `callback` . -------------------------------------------------------------------------------- /api/cookies.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:Cookies类 2 | 3 | > 会话(Cookie)查询与修改操作类 4 | 5 | 进程: [主进程](../glossary.md#主进程) 6 | 7 | ```JavaScript 8 | const {session} = require('electron') 9 | //查询所有Cookie。 10 | session.defaultSession.cookies.get({}, (error, cookies) => { 11 | console.log(error, cookies) 12 | }) 13 | //查询与特定网址相关联的所有Cookie。 14 | session.defaultSession.cookies.get({url: 'http://www.github.com'}, (error, cookies) => { 15 | console.log(error, cookies) 16 | }) 17 | //设置具有给定Cookie数据的Cookie; 18 | //如果存在相同的Cookie,则覆盖。 19 | const cookie = {url: 'http://www.github.com', name: 'dummy_name', value: 'dummy'} 20 | session.defaultSession.cookies.set(cookie, (error) => { 21 | if (error) console.error(error) 22 | }) 23 | ``` 24 | 25 | ## 实例事件 26 | 27 | #### 事件: 'changed' 28 | > 触发:**当Cookie因增加,编辑,删除,过期等改变时** 29 | 30 | * `event` Event 31 | * `cookie` [Cookie](structures/cookie.md) - 被改变的Cookie 32 | * `cause` String - 修改方式,可选以下: 33 | * `explicit` - 直接改变 34 | * `overwrite` - 自动擦除并覆盖 35 | * `expired` - 过期后自动删除 36 | * `evicted` - 跟随垃圾收集过程销毁 37 | * `expired-overwrite` - 用已过期的数据覆盖 38 | * `removed` Boolean - `true` 已删除, `false` 其它. 39 | 40 | ## 实例方法 41 | 42 | #### `cookies.get(filter, callback)` 43 | > 用途:**获取所有匹配 `filter`的Cookie** 44 | 45 | * `filter` Object 46 | * `url` String (可选) -关联Cookie的URL. 不存在则所有网址的Cookie。 47 | * `name` String (可选) - 按名称过滤Cookie。 48 | * `domain` String (可选) - 按 `domains`域或子域检索Cookie。 49 | * `path` String (可选) - 按 `path`路径检索Cookie。 50 | * `secure` Boolean (可选) -按照其Secure属性排序 51 | * `session` Boolean (可选) - 排除会话或持久Cookie 52 | * `callback` Function 53 | * `error` Error 54 | * `cookies` Cookies[] - [`cookie`](structures/cookie.md) 对象的数组。 55 | 56 | 当 `callback(error, cookies)` 完成后调用 `callback` 57 | 58 | #### `cookies.set(details, callback)` 59 | > 用途:**用 `details`创建或设置一个Cookie** 60 | 61 | * `details`对象 62 | * `url` String - 关联Cookie的URL。 63 | * `name` String(可选) - Cookie的名称。如果省略,默认为空。 64 | * `value` String(可选) - Cookie的值。如果省略,默认为空。 65 | * `domain` String(可选) - Cookie的域。如果省略,默认为空。 66 | * `path` String(可选) - Cookie的路径。如果省略,默认为空。 67 | * `secure` Boolean(可选) - Cookie是否应标记为安全。默认 为`false`。 68 | * `httpOnly` Boolean(可选) - Cookie是否应标记为仅HTTP。默认为 `false`。 69 | * `expirationDate` Double (可选) - Cookie的过期日期(秒级)。如果省略,则Cookie成为临时会话。 70 | * `callback` Function 71 | * `error` Error 72 | 73 | 当 `callback(error)`完成后,用 `details`, `callback`设置Cookie 74 | 75 | #### `cookies.remove(url, name, callback)` 76 | > 用途:**删除匹配 `url`和 `name`的Cookie** 77 | 78 | * `url` String - 关联Cookie的URL。 79 | * `name` String - 要删除的Cookie的名称。 80 | * `callback` Function 81 | 82 | 当 `callback()` 完成后,用 `url` 和 `name`, `callback`删除对应的Cookie 83 | 84 | #### `cookies.flushStore(callback)` 85 | > 用途:**清理存储数据,将未写入的Cookie数据写到磁盘中** 86 | 87 | * `callback` Function -------------------------------------------------------------------------------- /api/crash-reporter.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:crashReporter类(应用奔溃报告) 2 | 3 | >将崩溃报告提交到远程服务器。 4 | 5 | 进程: [主进程](../glossary.md#主进程), [渲染进程](../glossary.md#渲染进程) 6 | 7 | 以下是自动向远程服务器提交崩溃报告的示例: 8 | ```JavaScript 9 | const {crashReporter} = require('electron') 10 | 11 | crashReporter.start({ 12 | productName: 'YourName', 13 | companyName: 'YourCompany', 14 | submitURL: 'https://your-domain.com/url-to-submit', 15 | uploadToServer: true 16 | }) 17 | ``` 18 | 19 | 要设置服务器以接受和处理崩溃报告,您可以使用以下项目: 20 | 21 | * [socorro](https://github.com/mozilla/socorro) 22 | * [mini-breakpad-server](https://github.com/electron/mini-breakpad-server) 23 | 24 | 崩溃报告保存在相对于应用程序的临时目录文件夹中。 25 | 26 | 对于 `YourName`的 `productName`,崩溃报告将存储在临时目录里的 `YourName Crashes`的文件夹中. 27 | 28 | 你也可以在启动崩溃报告器之前通过 `app.setPath('temp', '/my/custom/temp')`定义相应目录. 29 | 30 | ## 方法 31 | 32 | ### `crashReporter.start(options)` 33 | > 用途:**开始收集奔溃报告** 34 | 35 | * `options` Object 36 | * `companyName` String (可选) 37 | * `submitURL` String - 以POST接收数据的URL 38 | * `productName` String (可选) - 默认为 `app.getName()`. 39 | * `uploadToServer` Boolean (可选) - 是否上传奔溃报告至系统服务,默认为 `true`. 40 | * `ignoreSystemCrashHandler` Boolean (可选) - 默认为 `false`. 41 | * `extra` Object (可选) - 一个你可以定义的对象,附带在崩溃报告上一起发送 . 只有字符串属性可以被正确发送,不支持嵌套对象. 42 | 43 | 此方法在使用任何其他 `crashReporter` API之前调用. 44 | 45 | 您可从中收集崩溃报告的每个进程(主/渲染器)。 46 | 47 | 当从不同进程调用时,可以向 `crashReporter.start`传递不同的选项。 48 | 49 | **注意**由于通过`child_process`模块创建的子进程无法访问Electron模块。因此,请使用`process.crashReporter.start`来收集它们的崩溃报告。传递的选项与上面一致,多了一个 `crashesDirectory`(时存储崩溃报告的目录)。你也可以通过调用`process.crash()`来测试这个过程。 50 | 51 | **注意:**要在Windows中收集子进程的崩溃报告,您还需要添加此额外的代码。这将启动监控和发送崩溃报告的过程。请用适当的值替换 `submitURL`, `productName`和 `crashesDirectory`。 52 | 53 | **注意:**如果你需要在第一次调用 `start`后发送额外的/更新的 `extra`参数,你可以: 54 | 55 | 在macOS上调用 `setExtraParameter`. 56 | 57 | 在Linux或WIN上用新的/更新的 `extra`参数再次调用 `start`. 58 | 59 | ```js 60 | const args = [ 61 | `--reporter-url=${submitURL}`, 62 | `--application-name=${productName}`, 63 | `--crashes-directory=${crashesDirectory}` 64 | ] 65 | const env = { 66 | ELECTRON_INTERNAL_CRASH_SERVICE: 1 67 | } 68 | spawn(process.execPath, args, { 69 | env: env, 70 | detached: true 71 | }) 72 | ``` 73 | 74 | **注意:**在macOS上,Electron是使用新的 `crashpad`客户端进行崩溃收集和报告,可以从主,渲染器进程和通过 `child_process`模块创建的任何子进程中收集崩溃。 75 | 76 | 如果要启用崩溃报告,则需要使用 `crashReporter.start`从主进程初始化 `crashpad`。 77 | 78 | 一旦这样初始化,crashpad处理程序收集来自所有进程的崩溃。 79 | 80 | 你必须从渲染器进程调用 `crashReporter.start`,否则渲染器进程的奔溃报告将不含 `companyName`, `productName`或任何 `extra`信息。 81 | 82 | ### `crashReporter.getLastCrashReport()` 83 | > 用途:**返回上次崩溃报告的日期和 ID[`CrashReport`](structures/crash-report.md)** 84 | 85 | 如果没有发送崩溃报告或崩溃报告器尚未启动,则返回 `nul`。 86 | 87 | ### `crashReporter.getUploadedReports()` 88 | > 用途:**返回所有上传的崩溃报告。每个报告包含日期和上传的ID** 89 | 90 | ### `crashReporter.getUploadToServer()` _Linux_ _macOS_ 91 | > 用途:**判断是否已将报告提交到服务器** 92 | 93 | 返回 `Boolean` - 通过 `start`方法或 `setUploadToServer`设置 94 | 95 | **注意:** 该API仅限主进程内调用 96 | 97 | ### `crashReporter.setUploadToServer(uploadToServer)` _Linux_ _macOS_ 98 | > 用途:**判断是否已将报告提交到服务器** 99 | 100 | * `uploadToServer` Boolean _Linux_ _macOS_ - 是否应将报告提交到服务器 101 | 102 | 通常,是否提交是由用户对系统进行偏好设置而决定的.且不能在 `start`之前调用该方法,否则无效. 103 | 104 | **注意:** 该API仅限主进程内调用 105 | 106 | ### `crashReporter.setExtraParameter(key, value)` _macOS_ 107 | > 用途:**设置要与崩溃报告一起发送的额外参数** 108 | 109 | * `key` String - 参数键。 110 | * `value` String - 参数值。指定 `null`或 `undefined`将从额外的参数中删除键。 111 | 112 | 113 | 当调用 `start`时,除了通过 `extra`选项设置的值之外,此处指定值也将被发送。 114 | 115 | 此API仅在macOS上可用, `start` 首次调用后,如果您希望在 在Linux和Windows上添加或更新额外参数, 116 | 117 | 您可以更新 `extra`选项并再次调用 `start`。 118 | 119 | ## 崩溃报告负载 120 | 121 | 崩溃报告将发送下面 `multipart/form-data` `POST` 型的数据给 `submitURL` : 122 | 123 | * `ver` String - Electron 版本. 124 | * `platform` String - 例如 'win32'. 125 | * `process_type` String - 例如 'renderer'. 126 | * `guid` String - 例如 '5e1286fc-da97-479e-918b-6bfb0c3d1c72' 127 | * `_version` String - `package.json` 版本. 128 | * `_productName` String - `crashReporter` `options`对象中的产品名字. 129 | * `prod` String - 基础产品名字. 这种情况为 Electron. 130 | * `_companyName` String - `crashReporter` `options`对象中的公司名字. 131 | * `upload_file_minidump` File - `minidump` 格式的崩溃报告. 132 | * `crashReporter` 中的 `extra` 对象的所有等级和一个属性. 133 | `options` object -------------------------------------------------------------------------------- /api/debugger.md: -------------------------------------------------------------------------------- 1 | # 本文介绍: Debugger类(调试工具) 2 | 3 | > 用于Chrome远程调试协议的替代传输。 4 | 5 | 进程: [主进程](../glossary.md#主进程) 6 | 7 | Chrome调试工具在JavaScript运行时具有[特殊绑定][rdp],允许与页面交互并对其进行检测。 8 | ```JavaScript 9 | const {BrowserWindow} = require('electron') 10 | let win = new BrowserWindow() 11 | 12 | try { 13 | win.webContents.debugger.attach('1.1') 14 | } catch (err) { 15 | console.log('Debugger attach failed : ', err) 16 | } 17 | 18 | win.webContents.debugger.on('detach', (event, reason) => { 19 | console.log('Debugger detached due to : ', reason) 20 | }) 21 | 22 | win.webContents.debugger.on('message', (event, method, params) => { 23 | if (method === 'Network.requestWillBeSent') { 24 | if (params.request.url === 'https://www.github.com') { 25 | win.webContents.debugger.detach() 26 | } 27 | } 28 | }) 29 | 30 | win.webContents.debugger.sendCommand('Network.enable') 31 | ``` 32 | 33 | ### 实例方法 34 | 35 | #### `debugger.attach([protocolVersion])` 36 | > 用途:**将调试器附加到 `webContents`** 37 | 38 | * `protocolVersion` String(可选) - 请求的调试协议版本。 39 | 40 | #### `debugger.isAttached()` 41 | > 用途:**判断调试器是否已附加到`webContents`** 42 | 43 | #### `debugger.detach()` 44 | > 用途:**从`webContents`里分离调试器** 45 | 46 | #### `debugger.sendCommand(method[, commandParams, callback])` 47 | > 用途:**发送给定命令到调试目标** 48 | 49 | * `method` String - 方法名, 名称通过远程调试协议定义. 50 | * `commandParams` Object (可选) -带请求参数的JSON对象。 51 | * `callback` Function (可选) - 响应方法 52 | * `error` Object - 错误后的指示命令 53 | * `result` Any - 由远程调试协议中的命令描述的“returns”属性定义的响应。 54 | 55 | ### 实例事件 56 | 57 | #### 事件: 'detach' 58 | > 触发:**在 `webContents`关闭 或 `webContents` 调用调试工具时** 59 | 60 | * `event` Event 61 | * `reason` String -分离调试器的原因。 62 | 63 | 64 | #### 事件: 'message' 65 | > 触发:**调试提交报告时** 66 | 67 | * `event` Event 68 | * `method` String - 方法名 69 | * `params` Object - 由远程调试协议中的 `parameters` 属性定义的事件参数。 70 | 71 | [rdp]: https://developer.chrome.com/devtools/docs/debugger-protocol 72 | [`webContents.findInPage`]: web-contents.md#contentsfindinpagetext-options -------------------------------------------------------------------------------- /api/desktop-capturer.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:捕获桌面资源 2 | 3 | > 通过[`navigator.webkitGetUserMedia`] API 捕获 audio 或 video等媒体资源 4 | 5 | 进程: [渲染进程](../glossary.md#渲染进程) 6 | 7 | 从 `Electron`桌面应用中捕获硬盘: 8 | 9 | ```JavaScript 10 | // In the renderer process. 11 | const {desktopCapturer} = require('electron') 12 | 13 | desktopCapturer.getSources({types: ['window', 'screen']}, (error, sources) => { 14 | if (error) throw error 15 | for (let i = 0; i < sources.length; ++i) { 16 | if (sources[i].name === 'Electron') { 17 | navigator.webkitGetUserMedia({ 18 | audio: false, 19 | video: { 20 | mandatory: { 21 | chromeMediaSource: 'desktop', 22 | chromeMediaSourceId: sources[i].id, 23 | minWidth: 1280, 24 | maxWidth: 1280, 25 | minHeight: 720, 26 | maxHeight: 720 27 | } 28 | } 29 | }, handleStream, handleError) 30 | return 31 | } 32 | } 33 | }) 34 | 35 | function handleStream (stream) { 36 | document.querySelector('video').src = URL.createObjectURL(stream) 37 | } 38 | 39 | function handleError (e) { 40 | console.log(e) 41 | } 42 | ``` 43 | 当使用这个方法的时候,不必指定 `chromeMediaSourceId`. 44 | 45 | 当调用 `navigator.webkitGetUserMedia` 创建一个约束对象后. 46 | 47 | 如果你想使用 `desktopCapturer` 的资源,您必须设置 `chromeMediaSource` 为 `desktop` , `audio` 为 `false`. 48 | 49 | 如果你想捕获整个桌面的 audio 和 video,您必须设置 `chromeMediaSource` 为 `screen` , `audio` 为 `true`. 50 | 51 | 52 | ## 方法 53 | 54 | ### `desktopCapturer.getSources(options, callback)` 55 | > 用途:**获取可用的桌面媒体源的信息并调用callback** 56 | 57 | * `options` Object 58 | * `types` String[] - 列出可捕获的桌面资源类型的String 数组, 可用类型为 `screen` 和 `window`. 59 | * `thumbnailSize` Object (可选) - 等比缩放的缩图尺寸, 默认为 `{width: 150, height: 150}`. 60 | * `callback` Function 61 | * `error` Error 62 | * `sources` [DesktopCapturerSource[]](structures/desktop-capturer-source.md) 63 | 64 | `sources` 是个[`DesktopCapturerSource`](structures/desktop-capturer-source.md)对象数组, 每个 `DesktopCapturerSource` 表示一个捕获的屏幕或窗口并有如下属性 : 65 | * `id` String - 在 `navigator.webkitGetUserMedia` 中使用的捕获窗口或屏幕的 id . 格式为 `window:XX` 或者 `screen:XX`, `XX` 是一个随机数. 66 | * `name` String - 捕获窗口或屏幕的描述名 . 如果资源为屏幕,名字为 `Entire Screen` 或 `Screen `; 如果资源为窗口, 名字为窗口的标题. 67 | * `thumbnail` [NativeImage](NativeImage.md) - 缩略图. 68 | 69 | **注意:** 不能保证 `source.thumbnail` 的 尺寸 和 `options` 中的 `thumnbailSize` 总是一致. 因为它取决于屏幕或窗口的缩放比例. 70 | 71 | [`navigator.webkitGetUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/Navigator/getUserMedia -------------------------------------------------------------------------------- /api/download-item.md: -------------------------------------------------------------------------------- 1 | ## 本文介绍: 应用中的文件下载 2 | 3 | > 控制从远程源的文件下载。 4 | 5 | 进程: [主进程](../glossary.md#主进程) 6 | 7 | `DownloadItem`(下载项)是一个在Electron中展示下载项的[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter) 8 | 9 | 它被用于 `Session`类中的 `will-download`事件,并允许用户控制下载项。 10 | 11 | ```JavaScript 12 | //主进程中 13 | const {BrowserWindow} = require('electron') 14 | let win = new BrowserWindow() 15 | win.webContents.session.on('will-download', (event, item, webContents) => { 16 | //设置保存路径,使Electron不提示保存对话框。 17 | item.setSavePath('/tmp/save.pdf') 18 | 19 | item.on('updated', (event, state) => { 20 | if (state === 'interrupted') { 21 | console.log('下载已中断,但可以恢复') 22 | } else if (state === 'progressing') { 23 | if (item.isPaused()) { 24 | console.log('下载已暂停') 25 | } else { 26 | console.log(`Received bytes: ${item.getReceivedBytes()}`) 27 | } 28 | } 29 | }) 30 | item.once('done', (event, state) => { 31 | if (state === 'completed') { 32 | console.log('下载成功') 33 | } else { 34 | console.log(`下载失败: ${state}`) 35 | } 36 | }) 37 | }) 38 | ``` 39 | 40 | ### 实例事件 41 | 42 | #### 事件: 'updated' 43 | > 触发:**下载获得更新且未完成时** 44 | 45 | * `event` Event 46 | * `state` String,可选以下状态: 47 | * `progressing` - 下载正在进行中。 48 | * `interrupted` - 下载已中断但可以恢复。 49 | 50 | #### 事件: 'done' 51 | > 触发:**下载处于完成状态(如已完成,被 `downloadItem.cancel()`取消,意外中断)** 52 | 53 | * `event` Event 54 | * `state` String,可选以下状态: 55 | * `completed` - 下载已成功完成。 56 | * `cancelled` - 下载已取消。 57 | * `interrupted`- 下载已中断,无法恢复。 58 | 59 | ### 实例方法 60 | 61 | #### `downloadItem.setSavePath(path)` 62 | > 用途:**设置下载目录** 63 | 64 | * `path` String - 下载项目的保存路径。 65 | 66 | API仅在会话的 `will-download` 回调函数中可用。 67 | 如果用户未通过API设置保存路径,Electron将使用原始保存路径(通常提示保存对话框)。 68 | 69 | #### `downloadItem.getSavePath()` 70 | > 用途:**返回下载目录** 71 | 72 | 通过 `downloadItem.setSavePath(path)` 设置的路径或从保存对话框中选择的路径。 73 | 74 | #### `downloadItem.pause()` 75 | > 用途:**暂停下载** 76 | 77 | #### `downloadItem.isPaused()` 78 | > 用途:**判断下载是否已被暂停** 79 | 80 | #### `downloadItem.resume()` 81 | > 用途:**恢复已暂停的下载** 82 | 83 | **注意:** 要启用可继续的下载项,您正在下载的服务器必须支持范围请求,并提供 `Last-Modified`和 `ETag`头值。 否则 `resume()`将关闭以前收到的字节,并从头开始重新下载。 84 | 85 | #### `downloadItem.canResume()` 86 | > 用途:**判断下载是否可以恢复** 87 | 88 | #### `downloadItem.cancel()` 89 | > 用途:**取消下载** 90 | 91 | #### `downloadItem.getURL()` 92 | > 用途:**获取下载项的链接地址** 93 | 94 | #### `downloadItem.getMimeType()` 95 | > 用途:**获取下载项的文件mime类型** 96 | 97 | #### `downloadItem.hasUserGesture()` 98 | > 用途:**判断下载是否具有用户手势** 99 | 100 | #### `downloadItem.getFilename()` 101 | > 用途:**获取下载项的文件名** 102 | 103 | **注意:**文件名不一定与保存在本地磁盘中的实际文件名相同。如果用户在提示的下载保存对话框中更改文件名,则保存文件的实际名称将不同。 104 | 105 | #### `downloadItem.getTotalBytes()` 106 | > 用途:**获取下载项的文件大小(以bytes字节为单位)** 107 | 如果大小未知,则返回0。 108 | 109 | #### `downloadItem.getReceivedBytes()` 110 | > 用途:**获取下载项的已接收字节数(以bytes字节为单位)** 111 | 112 | #### `downloadItem.getContentDisposition()` 113 | > 用途:**获取下载项的响应头的Content-Disposition字段(字符串)** 114 | 115 | #### `downloadItem.getState()` 116 | > 用途:**获取下载项的当前状态** 117 | 118 | 可以是 `progressing`下载中, `completed`已完成, `cancelled`已取消, `interrupted`中断且无法恢复. 119 | 120 | **注意:**以下方法适用于在会话重新启动时恢复 `cancelled`项。 121 | 122 | #### `downloadItem.getURLChain()` 123 | > 用途:**获取下载项的完整下载链接(包含任何重定向)(字符串)** 124 | 125 | #### `downloadItem.getLastModifiedTime()` 126 | > 用途:**获取下载项的Last-Modified标头值(字符串)** 127 | 128 | #### `downloadItem.getETag()` 129 | > 用途:**获取下载项的ETag头值(字符串)** 130 | 131 | #### `downloadItem.getStartTime()` 132 | > 用途:**获取下载项的开始下载时间(秒级)(字符串)** -------------------------------------------------------------------------------- /api/environment-variables.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:环境变量 2 | > 设置变量,可以不必更改代码的控制应用程序配置和行为。 3 | 4 | 某些Electron行为由环境变量控制,因为它们比命令行和代码更早地初始化。 5 | 6 | POSIX shell示例: 7 | ```bash 8 | $ export ELECTRON_ENABLE_LOGGING=true 9 | $ electron 10 | ``` 11 | 12 | Windows控制台示例: 13 | ```powershell 14 | > set ELECTRON_ENABLE_LOGGING=true 15 | > electron 16 | ``` 17 | 18 | ## 生产变量 19 | 20 | 下面的环境变量主要用于应用运行时。 21 | 22 | ### `GOOGLE_API_KEY` 23 | Electron包含用于向Google地理编码网络服务发出请求的硬编码API密钥。因为此API密钥包含在每个版本的Electron中,所以通常会超过其使用配额。 24 | 25 | 要解决此问题,您可以在环境中提供自己的Google API密钥。将以下代码放置在主进程文件中,然后再打开任何可以进行地理编码请求的浏览器窗口: 26 | 27 | ```JavaScript 28 | process.env.GOOGLE_API_KEY = 'YOUR_KEY_HERE' 29 | ``` 30 | 31 | 有关如何获取谷歌API密钥的说明,请访问:[此页](https://www.chromium.org/developers/how-tos/api-keys)。 32 | 33 | 默认情况下,新生成的Google API密钥可能不允许进行地理编码请求。要启用地理编码请求,请访问:[此页](https://console.developers.google.com/apis/api/geolocation/overview)。 34 | 35 | ### `ELECTRON_NO_ASAR` 36 | 禁用ASAR支持。这个变量只有在设置 `ELECTRON_RUN_AS_NODE`派生和催生的子进程中支持。 37 | 38 | ### `ELECTRON_RUN_AS_NODE` 39 | 将该进程作为正常的Node.js进程启动。 40 | 41 | ### `ELECTRON_NO_ATTACH_CONSOLE` _Windows_ 42 | 不要附加到当前控制台会话。 43 | 44 | ### `ELECTRON_FORCE_WINDOW_MENU_BAR` _Linux_ 45 | 不要使用Linux上的全局菜单栏。 46 | 47 | ## 开发变量 48 | 49 | 下面的环境变量主要用于开发和调试的目的。 50 | 51 | ### `ELECTRON_ENABLE_LOGGING` 52 | 将Chrome的内部日志记录打印到控制台。 53 | 54 | ### `ELECTRON_LOG_ASAR_READS` 55 | 当Electron从ASAR文件读取时,将读偏移和文件路径记录到系统 `tmpdir`。生成的文件可以提供给ASAR模块以优化文件排序。 56 | 57 | ### `ELECTRON_ENABLE_STACK_DUMPING` 58 | Electron崩溃时,将堆栈跟踪打印到控制台。 59 | 60 | 如果 `crashReporter`启动,这个环境变量将不起作用。 61 | 62 | ### `ELECTRON_DEFAULT_ERROR_MODE` _Windows_ 63 | Electron崩溃时,显示Windows的崩溃对话框。 64 | 65 | 如果 `crashReporter`启动,这个环境变量将不起作用。 -------------------------------------------------------------------------------- /api/file-object.md: -------------------------------------------------------------------------------- 1 | # 本文介绍: `File` 的应用(本地文件操作接口) 2 | 3 | >使用H5的 `File` API操作本地文件 4 | 5 | Electron增添了 `path`属性的 `File`接口,用来获得文件真实路径。 6 | 7 | 拖入文件到app并显示真实路径的例子: 8 | 9 | ```html 10 |
11 | 拖拽文件到这里 12 |
13 | 14 | 30 | ``` -------------------------------------------------------------------------------- /api/frameless-window.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:无框窗口的应用与操作 2 | 3 | > 没有工具栏或任何边框仅纯内容的窗口. 4 | 5 | ## 创建无框窗口 6 | 在 [BrowserWindow](browser-window.md)的 `options`中设置 `frame` 为 `false` 即可创建无框窗口. 7 | 8 | ```JavaScript 9 | const {BrowserWindow} = require('electron') 10 | let win = new BrowserWindow({width: 800, height: 600, frame: false}) 11 | win.show() 12 | ``` 13 | 14 | ### macOS上的替代方案 15 | 在macOS 10.9 Mavericks和更新版本中,有一种不同于设置 `frame`为 `false`的替代方法来生成无边框窗口。 16 | 17 | 无边框通常会隐藏标题栏以及失去对窗口的控制,如果你希望无边框的同时又保持对窗口的控制( `traffic lights`)。你可以通过设置下文的 `titleBarStyle`两个属性来实现: 18 | 19 | #### `hidden` 20 | 仅左上角有正常窗口控制( `traffic lights`)的无边框. 21 | 22 | ```JavaScript 23 | const {BrowserWindow} = require('electron') 24 | let win = new BrowserWindow({titleBarStyle: 'hidden'}) 25 | win.show() 26 | ``` 27 | 28 | #### `hidden-inset` 29 | 在边缘嵌入窗口控制( `traffic lights`) 30 | 31 | ```JavaScript 32 | const {BrowserWindow} = require('electron') 33 | let win = new BrowserWindow({titleBarStyle: 'hidden-inset'}) 34 | win.show() 35 | ``` 36 | 37 | 38 | ## 透明窗口 39 | 设置 `transparent`为 `true`可使无框窗口透明: 40 | 41 | ```JavaScript 42 | const {BrowserWindow} = require('electron') 43 | let win = new BrowserWindow({transparent: true, frame: false}) 44 | win.show() 45 | ``` 46 | 47 | ### 限制 48 | 49 | * 无法点击穿透区域(透明窗口实质是个矩形窗口,假设内容是圆形,那么圆形与矩形的交集处透明区域无法点击穿透)。详见[讨论帖](https://github.com/electron/electron/issues/1335) 50 | * 透明窗口是不可调整大小的。在某些平台上,设置 `resizable`为 `true`也许会造成透明窗口停止工作。 51 | * `blur`滤光器只适用于网页,所以没法将模糊效果用于窗口之下 52 | * 在Windows系统中,当DWM被禁用时透明窗口不会工作。 53 | * Linux用户需要命令行 `--enable-transparent-visuals --disable-gpu` 54 | 来禁用GPU以及允许ARGB去渲染透明窗口,这是由于一个Linux上的上游bug造成的 [详见此文](https://code.google.com/p/chromium/issues/detail?id=369209) 55 | * 在Mac上,透明窗口的阴影不会显示出来. 56 | 57 | ## 临时的穿透方案 58 | 使用[win.setIgnoreMouseEvents(ignore)][ignore-mouse-events] API创建可穿透窗口(即不响应所有的鼠标事件): 59 | ```javascript 60 | const {BrowserWindow} = require('electron') 61 | let win = new BrowserWindow() 62 | win.setIgnoreMouseEvents(true) 63 | ``` 64 | 65 | ## 可拖动区域 66 | 默认情况下,无框窗口是不可拖动的。 67 | 68 | 您需要在CSS中设置 `-webkit-app-region: drag`设定可拖动区域,或设置 `-webkit-app-region: no-drag` 禁止拖动的区域。 69 | 70 | 需要注意的是,目前只支持矩形区域。 71 | 72 | ```html 73 | 74 | 75 | ``` 76 | 另外需要注意的是,如果你设置了整个窗口可拖动,你必须标记按钮为不可拖动,否则用户无法点击它们: 77 | ```css 78 | button { 79 | -webkit-app-region: no-drag; 80 | } 81 | ``` 82 | 如果你设置一个自定义的标题栏可拖动,你同样需要将标题栏中所有按钮设置为不可拖动. 83 | 84 | ## 文本选择 85 | 在一个无框窗口中,拖动动作可能与文本选择发生冲突。比如,当你拖动标题栏,可能会变成选中标题栏上的文本。 86 | 87 | 为了防止这种情况发生,你需要向下面这样在一个可拖动区域中禁用文本选择: 88 | 89 | ```css 90 | .titlebar { 91 | -webkit-user-select: none; 92 | -webkit-app-region: drag; 93 | } 94 | ``` 95 | 96 | ## 上下文菜单 97 | 在一些平台上,可拖动区域会被认为是非客户端框架(non-client frame),当你点击右键时,会弹出系统菜单。 98 | 99 | 为了保证上下文菜单在所有平台下正确的显示,你不应该在可拖动区域使用自定义上下文菜单。 100 | 101 | [ignore-mouse-events]: browser-window.md#winsetignoremouseeventsignore -------------------------------------------------------------------------------- /api/global-shortcut.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:全局快捷键 2 | > 应用于键盘无焦点时的键盘快捷键. 3 | 4 | 进程: [主进程](../glossary.md#主进程) 5 | 6 | `global-shortcut`模块可以便捷的设置(注册/注销)各种自定义操作的快捷键. 7 | 8 | **注意:** 这种快捷键是全局性的,即键盘没有聚焦于应用时,本模块需应用于在 `ready`后. 9 | 10 | ```JavaScript 11 | const {app, globalShortcut} = require('electron') 12 | 13 | app.on('ready', () => { 14 | //注册一个“CommandOrControl + X”快捷方式监听 15 | const ret = globalShortcut.register('CommandOrControl+X', () => { 16 | console.log('用户按下了 CommandOrControl+X') 17 | }) 18 | 19 | if (!ret) {console.log('快捷键注册失败')} 20 | 21 | // 检查快捷方式是否已注册。 22 | console.log(globalShortcut.isRegistered('CommandOrControl+X')) 23 | }) 24 | 25 | app.on('will-quit', () => { 26 | //取消已注册的一个快捷键。 27 | globalShortcut.unregister('CommandOrControl+X') 28 | 29 | //注销应用注册的所有快捷键 30 | globalShortcut.unregisterAll() 31 | }) 32 | ``` 33 | 34 | ## 事件方法 35 | 36 | ### `globalShortcut.register(accelerator, callback)` 37 | > 用途:**注册快捷键 `accelerator`** 38 | 39 | * `accelerator` [Accelerator](accelerator.md) 40 | * `callback` Function 按下快捷键后的操作 41 | 42 | 如果快捷键已经被其他应用程序注册了,这个 `callback`将静默失败。 43 | 44 | ### `globalShortcut.isRegistered(accelerator)` 45 | > 用途:**判断快捷键 `accelerator`是否已经被注册** 46 | 47 | * `accelerator` [Accelerator](accelerator.md) 48 | 49 | ### `globalShortcut.unregister(accelerator)` 50 | > 用途:**注销快捷键 `accelerator`** 51 | 52 | * `accelerator` [Accelerator](accelerator.md) 53 | 54 | ### `globalShortcut.unregisterAll()` 55 | > 用途:**注销应用注册的所有快捷键** -------------------------------------------------------------------------------- /api/incoming-message.md: -------------------------------------------------------------------------------- 1 | ## 本文介绍: 处理对HTTP / HTTPS请求的响应 2 | 3 | > 通常用于HTTP/HTTPS请求失败/成功等处理. 4 | 5 | 进程: [主进程](../glossary.md#主进程) 6 | 7 | `IncomingMessage`是由 [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)响应[可读流](https://nodejs.org/api/stream.html#stream_readable_streams)接口 8 | 9 | ### 实例事件 10 | 11 | #### 事件: 'data' 12 | > 用途:**响应或回调传送到应用的数据** 13 | 14 | * `chunk` Buffer - 响应正文的数据块. 15 | 16 | #### 事件: 'end' 17 | > 触发:**响应正文已结束时** 18 | 19 | #### 事件: 'aborted' 20 | > 触发:**正在进行的HTTP事务期间请求已取消时** 21 | 22 | #### 事件: 'error' 23 | > 触发:**流响应数据事件遇到错误时** 24 | 25 | 返回 `error` Error - 错误字符串,标识失败原因 26 | 27 | 例如,服务器已关闭但响应仍在流式传输,则将在响应对象上发出一个 `error` 事件,随后在请求对象上将会出现一个 `close` 事件。 28 | 29 | ### 实例属性 30 | #### `response.statusCode` 31 | > 属性:**HTTP响应状态的数字代码** 32 | 33 | #### `response.statusMessage` 34 | > 属性:**HTTP响应状态的消息文本** 35 | 36 | #### `response.headers` 37 | > 属性:**HTTP响应头对象** 38 | 39 | 格式如下: 40 | * 所有标题名称均为小写。 41 | * 每个响应名称必须是对象中的键. 42 | * 每个响应名称和它的值是可匹配的 43 | 44 | #### `response.httpVersion` 45 | > 属性:**HTTP协议版本号,典型值是 `1.0`或 `1.1`** 46 | 47 | #### `response.httpVersionMajor` 48 | > 属性:**HTTP协议的主版本号** 49 | 50 | #### `response.httpVersionMinor` 51 | > 属性:**HTTP协议的次版本号** -------------------------------------------------------------------------------- /api/ipc-main.md: -------------------------------------------------------------------------------- 1 | # 本文介绍: ipcMain(主进程中回复或接收渲染进程发送的消息) 2 | > 在主进程中处理由渲染进程发起的异步通信. 3 | 4 | 进程: [主进程](../glossary.md#主进程) 5 | 6 | `ipcMain` 模块是类[EventEmitter](https://nodejs.org/api/events.html)类的一个实例. 7 | 8 | 浅显的打个比方,渲染进程给主进程挂个号,这里就开始忙活起来.当然,你也可以从主进程中向渲染进程发送消息. 9 | 10 | ## 发送消息 11 | 如果从主进程向渲染进程发送消息,请查看 [web-contents-send](web-contents.md#contentssendchannel-arg1-arg2-) 12 | 13 | * 发送消息,事件名为 `channel`. 14 | * 回应同步消息, 请设置 `event.returnValue`. 15 | * 回应异步消息, 请使用 `event.sender.send(...)`. 16 | 17 | 在主进程和渲染进程之间发送和处理消息的例子: 18 | ```JavaScript 19 | // 主进程中 20 | const {ipcMain} = require('electron') 21 | ipcMain.on('asynchronous-message', (event, arg) => { 22 | console.log(arg) // 输出 `ping` 23 | event.sender.send('asynchronous-reply', 'pong') 24 | }) 25 | 26 | ipcMain.on('synchronous-message', (event, arg) => { 27 | console.log(arg) // 输出 `ping` 28 | event.returnValue = 'pong' 29 | }) 30 | ``` 31 | 32 | ```JavaScript 33 | // 渲染进程中(即网页). 34 | const {ipcRenderer} = require('electron') 35 | console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // 输出 `pong` 36 | 37 | ipcRenderer.on('asynchronous-reply', (event, arg) => { 38 | console.log(arg) // 输出 `pong` 39 | }) 40 | ipcRenderer.send('asynchronous-message', 'ping') 41 | ``` 42 | 43 | ## 监听事件 44 | 45 | ### `ipcMain.on(channel, listener)` 46 | > 用途:**监听 `channel`,并调用 `listener(event, args...)` 处理新消息** 47 | 48 | * `channel` String 49 | * `listener` Function 50 | 51 | ### `ipcMain.once(channel, listener)` 52 | > 用途:**一次性监听 `channel`,当调用 `listener(event, args...)` 处理新消息后删除监听** 53 | 54 | * `channel` String 55 | * `listener` Function - 一次性的 `listener`. 56 | 57 | ### `ipcMain.removeListener(channel, listener)` 58 | > 用途:**从指定 `channel` 的监听数组中删除特定的 `listener`** 59 | 60 | * `channel` String 61 | * `listener` Function 62 | 63 | ### `ipcMain.removeAllListeners([channel])` 64 | > 用途:**删除所有监听,或指定 `channel` 的所有监听** 65 | 66 | * `channel` String (可选) 67 | 68 | ## 事件对象 69 | 传递给 `callback` 的 `event` 对象有如下方法: 70 | 71 | ### `event.returnValue` 72 | 将此设置成同步消息中返回的值. 73 | 74 | ### `event.sender` 75 | 返回发送消息的 `webContents` ,你可以调用 `event.sender.send` 来回复异步消息,详见[webContents.send][web-contents-send]. 76 | 77 | -------------------------------------------------------------------------------- /api/ipc-renderer.md: -------------------------------------------------------------------------------- 1 | # 本文介绍: ipcRenderer(从渲染进程发送消息至主进程) 2 | > 从渲染进程到主进程的异步通信 3 | 4 | 进程: [渲染进程](../glossary.md#渲染进程) 5 | 6 | `ipcRenderer`模块是[EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)类的一个实例。 7 | 8 | 它提供了几个方法,所以你可以从渲染进程(网页)发送同步和异步消息到主进程。您还可以从主流程接收回复。 9 | 10 | ## 事件方法 11 | 12 | ### `ipcRenderer.on(channel, listener)` 13 | > 用途:**监听 `channel`,并调用 `listener(event, args...)` 处理新消息** 14 | 15 | * `channel` String 16 | * `listener` Function 17 | 18 | ### `ipcRenderer.once(channel, listener)` 19 | > 用途:**一次性监听 `channel`,当调用 `listener(event, args...)` 处理新消息后删除监听** 20 | 21 | * `channel` String 22 | * `listener` Function - 一次性的 `listener` 方法. 23 | 24 | ### `ipcRenderer.removeListener(channel, listener)` 25 | > 用途:**从指定 `channel` 的监听数组中删除特定的 `listener`** 26 | 27 | * `channel` String 28 | * `listener` Function 29 | 30 | ### `ipcRenderer.removeAllListeners([channel])` 31 | > 用途:**删除所有监听,或指定 `channel` 的所有监听** 32 | 33 | * `channel` String (可选) 34 | 35 | ### `ipcRenderer.send(channel[, arg1][, arg2][, ...])` 36 | > 用途:**通过 `channel` 向主进程异步发送消息或任意参数** 37 | 38 | * `channel` String 39 | * `...args` any[] 40 | 41 | 参数将在JSON内部序列化,因此不会包含函数或原型链。主进程通过用ipcMain模块侦听 `channel`来处理它。 42 | 43 | ### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` 44 | > 用途:**通过 `channel` 向主进程同步发送消息或任意参数** 45 | 46 | * `channel` String 47 | * `...args` any[] 48 | 49 | 参数将在JSON内部序列化,因此不会包含函数或原型链。主进程通过用ipcMain模块侦听 `channel`来处理它,并通过设置 `event.returnValue` 来回复。 50 | 51 | **注意:**务必明确的一点是发送同步消息将阻止整个渲染进程。 52 | 53 | ### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` 54 | > 用途:**通过 `channel` 向主机页面(host page)的 `` 元素发送消息或任意参数** 55 | 56 | * `channel` String 57 | * `...args` any[] 58 | 59 | 类似 `ipcRenderer.send` ,但是事件是发往主机页面(host page)的 `` 元素,而不是主进程. -------------------------------------------------------------------------------- /api/locales.md: -------------------------------------------------------------------------------- 1 | # 本文介绍: 应用语言环境的判断 2 | 3 | >使用 `app.getLocale()` 接收返回语言环境值 4 | 5 | Electron 通过 Chromium的 `l10n_util` 库获取应用的语言环境。 6 | 7 | 以下是语言列表: 8 | 9 | | 语言代码 | 语言名称 | 10 | |---------------|---------------| 11 | | af | 南非荷兰语 | 12 | | am | 阿姆哈拉语 | 13 | | ar | 阿拉伯语 | 14 | | az | 阿塞拜疆 | 15 | | be | 白俄罗斯 | 16 | | bg | 保加利亚语 | 17 | | bh | 比哈里 | 18 | | bn | 孟加拉语 | 19 | | br | 布列塔尼 | 20 | | bs | 波斯尼亚语 | 21 | | ca | 加泰罗尼亚语 | 22 | | co | 科西嘉 | 23 | | cs | 捷克语 | 24 | | cy | 威尔士语 | 25 | | da | 丹麦语 | 26 | | de | 德语 | 27 | | de-AT | 德语(奥地利) | 28 | | de-CH | 德语(瑞士) | 29 | | de-DE | 德国(德国) | 30 | | el | 希腊语 | 31 | | en | 英文 | 32 | | en-AU | 英语(澳大利亚) | 33 | | en-CA | 英语(加拿大) | 34 | | en-GB | 英语(英国) | 35 | | en-NZ | 英语(新西兰) | 36 | | en-US | 英文(US) | 37 | | en-ZA | 英语(南非) | 38 | | eo | 世界语 | 39 | | es | 西班牙语 | 40 | | es-419 | 西班牙语(拉丁美洲) | 41 | | et | 爱沙尼亚语 | 42 | | eu | 巴斯克语 | 43 | | fa | 波斯语 | 44 | | fi | 芬兰语 | 45 | | fil | 菲律宾 | 46 | | fo | 法罗语 | 47 | | fr | 法语 | 48 | | fr-CA | 法语(加拿大) | 49 | | fr-CH | 法语(瑞士) | 50 | | fr-FR | 法语(法国) | 51 | | fy | 弗里斯兰语 | 52 | | ga | 爱尔兰 | 53 | | gd | 苏格兰盖尔语 | 54 | | gl | 加利西亚 | 55 | | gn | 瓜拉尼 | 56 | | gu | 古吉拉特语 | 57 | | ha | 豪萨 | 58 | | haw | 夏威夷语 | 59 | | he | 希伯来语 | 60 | | hi | 印度语 | 61 | | hr | 克罗地亚语 | 62 | | hu | 匈牙利语 | 63 | | hy | 亚美尼亚 | 64 | | ia | 国际语 | 65 | | id | 印尼语 | 66 | | is | 冰岛语 67 | | it | 意大利语 | 68 | | it-CH | 意大利语(瑞士) | 69 | | it-IT | 意大利(意大利) | 70 | | ja | 日语 | 71 | | jw | 爪哇 | 72 | | ka | 格鲁吉亚语 | 73 | | kk | 哈萨克斯坦 74 | | km | 柬埔寨 | 75 | | kn | 加纳达 | 76 | | ko | 韩语 | 77 | | ku | 库尔德语 | 78 | | ky | 吉尔吉斯斯坦 | 79 | | la | 拉丁语 | 80 | | ln | Lingala | 81 | | lo | Laothian | 82 | | lt | 立陶宛语 | 83 | | lv | 拉脱维亚语 84 | | mk | 马其顿 | 85 | | ml | 马拉雅拉姆 86 | | mn | 蒙古语 | 87 | | mo | 摩尔多瓦人 | 88 | | mr | 马拉地 | 89 | | ms | 马来西亚 | 90 | | mt | 马耳他语 | 91 | | nb | 挪威语(Bokmal) | 92 | | ne | 尼泊尔语 93 | | nl | 荷兰语 | 94 | | nn | 挪威语(Nynorsk) | 95 | | no | 挪威语 | 96 | | oc | 奥克西唐 97 | | om | Oromo | 98 | | or | Oriya | 99 | | pa | 旁遮普语 100 | | pl | 波兰语 | 101 | | ps | Pashto | 102 | | pt | 葡萄牙语 | 103 | | pt-BR | 葡萄牙语(巴西) | 104 | | pt-PT | 葡萄牙语(葡萄牙) | 105 | | qu | 盖丘亚 | 106 | | rm | 罗曼什 | 107 | | ro | 罗马尼亚语 | 108 | | ru | 俄语 | 109 | | sd | 信德 | 110 | | sh | 塞尔维亚-克罗地亚语 | 111 | | si | 僧伽罗语 | 112 | | sk | 斯洛伐克语 | 113 | | sl | 斯洛文尼亚语 | 114 | | sn | Shona | 115 | | so | 索马里 | 116 | | sq | 阿尔巴尼亚语 | 117 | | sr | 塞尔维亚语 | 118 | | st | Sesotho | 119 | | su | Sundㄧese | 120 | | sv | 瑞典语 | 121 | | sw | 斯瓦希里语 122 | | ta | 泰米尔语 123 | | te | 泰卢固语 | 124 | | tg | 塔吉克斯坦 125 | | th | 泰语 | 126 | | ti | Tigrinya | 127 | | tk | 土库曼斯坦 128 | | to | 汤加 | 129 | | tr | 土耳其语 | 130 | | tt | 鞑靼 | 131 | | tw | Twi | 132 | | ug | 维吾尔族 | 133 | | uk | 乌克兰语 | 134 | | ur | 乌尔都语 | 135 | | uz | 乌兹别克语 | 136 | | vi | 越南语 | 137 | | xh | Xhosa | 138 | | i | 意第绪语 | 139 | | yo | 约鲁巴 | 140 | | zh | 中文 | 141 | | zh-CN | 中文(简体) | 142 | | zh-TW | 中文(繁体) | 143 | | zu | 祖鲁 | -------------------------------------------------------------------------------- /api/menu-item.md: -------------------------------------------------------------------------------- 1 | ## 本文介绍: MenuItem类(菜单项的创建与修改) 2 | 3 | > 在程序菜单或上下文菜单中插入新的菜单项 4 | 5 | 进程: [主进程](../glossary.md#main-process) 6 | 7 | 您可以在 [`Menu`](menu.md)末尾查看示例. 8 | 9 | ### `new MenuItem(options)` 10 | 11 | * `options` Object 12 | * `click` Function (可选) - 单击菜单项被调用 `click(menuItem,browserWindow)` 13 | * `menuItem` MenuItem 14 | * `browserWindow` BrowserWindow 15 | * `event` Event 16 | * `role` String (可选) - 定义菜单项操作,指定为 `click` 属性时该项将会被忽略. 详见[任务章节](#roles). 17 | * `type` String (可选) - 可选`normal`, `separator`, `submenu`, `checkbox` 或 `radio`. 18 | * `label` String - (可选) 19 | * `sublabel` String - (可选) 20 | * `accelerator` [Accelerator](accelerator.md) (可选) 21 | * `icon` ([NativeImage](native-image.md) | String) (可选) 22 | * `enabled` Boolean (可选) - `false`表示菜单项显示为不可点击的灰色 23 | * `visible` Boolean (可选) - `false`表示菜单项完全隐藏。 24 | * `checked` Boolean (可选) - 仅 `checkbox`或 `radio`类型菜单项才需要指定。 25 | * `submenu` (MenuItemConstructorOptions[] | Menu) (可选) - 应为 `submenu` 类型菜单项而指定,如果指定了 `submenu`, 则 `type:'submenu'`可以省略。如果它的值不是 `Menu`,将自动转为 `Menu.buildFromTemplate`。 26 | * `id` String - 菜单的唯一id。如果id已被使用,它将被用作这个菜单项的参考位置 `position` 属性。 27 | * `position` String - 定义菜单的具体位置信息。 28 | 29 | ### Roles任务 30 | 31 | > `roles` 可使菜单项具有预定义行为. 32 | 33 | 在创建菜单项时,如果有匹配的方法,建议直接指定 `role` 属性而不是尝试在 `click`函数中手动实现该行为,这样可以给用户最好的使用体验。 34 | 35 | 当使用 `role`时, `label`和 `accelerator` 的值是可选的,默认将根据平台使用适当的值。 36 | 37 | `role`属性值可以为: 38 | 39 | * `undo` 40 | * `redo` 41 | * `cut` 42 | * `copy` 43 | * `paste` 44 | * `pasteandmatchstyle` 45 | * `selectall` 46 | * `delete` 47 | * `minimize` - 最小化当前窗口 48 | * `close` - 关闭当前窗口 49 | * `quit`- 退出应用 50 | * `reload` -重新加载当前窗口 51 | * `forcereload` - 重新加载当前窗口并忽略缓存。 52 | * `toggledevtools` - 在当前窗口中切换开发人员工具 53 | * `togglefullscreen` - 在当前窗口切换全屏模式 54 | * `resetzoom` - 聚焦页缩放级别重置为原始大小 55 | * `zoomin` - 聚焦页放大10% 56 | * `zoomout` - 聚焦页缩小10% 57 | * `editMenu` - 默认的 `编辑`菜单 (撤销, 复制等等) 58 | * `windowMenu` - 默认的 `窗口`菜单 (最小化, 关闭等等) 59 | 60 | 在 macOS 上也可使用下列 `role` : 61 | 62 | * `about` - 映射到 `orderFrontStandardAboutPanel`动作 63 | * `hide` - 映射到 `hide`动作 64 | * `hideothers` - 映射到 `hideOtherApplications`动作 65 | * `unhide` - 映射到 `unhideAllApplications`动作 66 | * `startspeaking` - 映射到 `startSpeaking`动作 67 | * `stoppeaking` - 映射到 `stopSpeaking`动作 68 | * `front` - 映射到 `arrangeInFront`动作 69 | * `zoom` - 映射到 `performZoom`动作 70 | * `window` - 子菜单是一个 `Window`菜单 71 | * `help` - 子菜单是一个 `帮助`菜单 72 | * `services` - 子菜单是一个 `服务`菜单 73 | 74 | 当在macOS上指定 `role`时, `label` 和 `accelerator`是唯一会影响MenuItem的选项。其他选项将被忽略。 75 | 76 | ### 实例属性 77 | 78 | #### `menuItem.enabled` 79 | > 属性:**是否启用该项** 80 | 81 | 此属性可以动态更改。 82 | 83 | #### `menuItem.visible` 84 | > 属性:**是否可见该项** 85 | 86 | 此属性可以动态更改。 87 | 88 | #### `menuItem.checked` 89 | > 属性:**该项是否已选中** 90 | 91 | `checkbox` 菜单项将在选中时打开或关闭 `checked`属性 92 | `radio`菜单项将在点击时打开其`checked`属性,并将关闭同一菜单中所有相邻项的该属性。 93 | 94 | 如果需要其他行为,您可以直接添加一个 `click`函数。 95 | 96 | 此属性可以动态更改。 97 | 98 | #### `menuItem.label` 99 | > 属性:**菜单项内容字符串** 100 | 101 | #### `menuItem.click` 102 | > 属性:**点击菜单项时需要触发的函数** -------------------------------------------------------------------------------- /api/net.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:Chromium原生网络库 2 | 3 | > 使用Chromium原生网络库发起HTTP/HTTPS请求 4 | 5 | 进程: [主进程](../glossary.md#主进程) 6 | 7 | `net` 模块是用于发出 HTTP(S) 请求问题的客户端 API。 8 | 9 | 它类似于Node.js的[HTTP](https://nodejs.org/api/http.html) 和 [HTTPS](https://nodejs.org/api/https.html)模块,但是它基于Chromium 的原生API 而非Node.js ,相对而言更适合处理 web 端的请求。 10 | 11 | 关于为什么使用 `net` 模块 而非Node.js,这里有个简要的原因列表: 12 | 13 | * 自动管理系统代理设置,支持 wpad 协议和 pac 代理配置文件。 14 | * 自动使用隧道通过 HTTPS 请求。 15 | * 支持 basic, digest, NTLM, Kerberos 或 negotiate 等认证方案的身份验证代理。 16 | * 支持流量监控代理: 用于访问控制和监控的Fiddler类代理。 17 | 18 | `net` 模块的 API 在设计上特别的模仿了 Node.js 的 API 从而达到比较接近的体验。也就是说,它非常相似 Node.js 的 [HTTP](https://nodejs.org/api/http.html)/[HTTPS](https://nodejs.org/api/https.html) 模块。 19 | 20 | 如何使用 `net` API的小例子: 21 | 22 | ```JavaScript 23 | const {app} = require('electron') 24 | app.on('ready', () => { 25 | const {net} = require('electron') 26 | const request = net.request('https://github.com') 27 | request.on('response', (response) => { 28 | console.log(`状态: ${response.statusCode}`) 29 | console.log(`文件头: ${JSON.stringify(response.headers)}`) 30 | response.on('data', (chunk) => { 31 | console.log(`正文: ${chunk}`) 32 | }) 33 | response.on('end', () => { 34 | console.log('没有更多的数据响应.') 35 | }) 36 | }) 37 | request.end() 38 | }) 39 | ``` 40 | 41 | `net` API 必须在 `ready` 事件后使用。否则会抛出一个错误。 42 | 43 | ## 方法 44 | 45 | ### `net.request(options)` 46 | > 用途:**根据 `options`对象中指定的协议方案发出安全和不安全的HTTP请求( [`ClientRequest`](./client-request.md))* 47 | 48 | * `options` (Object | String) - `ClientRequest` 的构造参数,使用提供的 `options` 创建一个[`ClientRequest`](./ client-request.md)实例。 -------------------------------------------------------------------------------- /api/power-monitor.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:监视电源状态 2 | 3 | >监视电源状态 4 | 5 | 进程: [主进程](../glossary.md#主进程) 6 | 7 | 该模块在主进程 `app` 模块的 `ready` 事件前使用. 8 | ```JavaScript 9 | const electron = require('electron') 10 | const {app} = electron 11 | 12 | app.on('ready', () => { 13 | electron.powerMonitor.on('suspend', () => { 14 | console.log('系统即将进入睡眠') 15 | }) 16 | }) 17 | ``` 18 | 19 | ## 事件列表 20 | 21 | ### 事件:'suspend' 22 | > 触发:**系统挂起时** 23 | 24 | ### 事件:`resume` 25 | > 触发:**系统恢复时** 26 | 27 | ### 事件:'on-ac'_Windows_ 28 | > 触发:**系统更改为交流电源时** 29 | 30 | ### 事件:'on-battery'_Windows_ 31 | > 触发:**系统更改为电池电源时** -------------------------------------------------------------------------------- /api/power-save-blocker.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:阻止系统进入低功耗(睡眠)模式 2 | 3 | > 当需要应用在前后台无间断工作时,应避免系统进入睡眠. 4 | 5 | 进程: [主进程](../glossary.md#主进程) 6 | ```JavaScript 7 | const {powerSaveBlocker} = require('electron') 8 | const id = powerSaveBlocker.start('prevent-display-sleep') 9 | console.log(powerSaveBlocker.isStarted(id)) 10 | powerSaveBlocker.stop(id) 11 | ``` 12 | 13 | ## 方法 14 | 15 | `powerSaveBlocker` 模块有如下方法: 16 | 17 | ### `powerSaveBlocker.start(type)` 18 | > 用途:**开始阻止系统进入睡眠模式.返回识别节能模块的整数( `Integer`)** 19 | 20 | * `type` String - 节电模块类型。 21 | * `prevent-app-suspension` - 阻止应用挂起.保持系统活跃,但允许屏幕关闭。如:下载文件或播放音频。 22 | * `prevent-display-sleep` - 防止显示器进入睡眠状态。保持系统和屏幕活动。如:播放视频。 23 | 24 | **注意:** `prevent-display-sleep`总是优先生效于 `prevent-app-suspension` 25 | 例如,一个API调用A请求 `prevent-app-suspension`,另一个调用B请求 `prevent-display-sleep`。只有当B停止了 `prevent-display-sleep`,A的 `prevent-app-suspension`才会生效. 26 | 27 | ### `powerSaveBlocker.stop(id)` 28 | > 用途:**停止指定的省电模式.返回节电阻止程序ID( `Integer`)** 29 | 30 | * `id` Integer - 通过 `powerSaveBlocker.start` 返回的保持活跃的 blocker id. 31 | 32 | ### `powerSaveBlocker.isStarted(id)` 33 | > 用途:**判断 `powerSaveBlocker`是否已经开始( `Boolean`)** 34 | 35 | * `id` Integer - 通过 `powerSaveBlocker.start` 返回的保持活跃的 blocker id. -------------------------------------------------------------------------------- /api/process.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:进程 2 | 3 | > 进展的相关属性和扩展管理 4 | 5 | 进程: [主进程](../glossary.md#主进程), [渲染进程](../glossary.md#渲染进程) 6 | 7 | Electron 中的 `process` 对象是[Node.js的`process` 对象](https://nodejs.org/api/process.html) 的扩展。 8 | 9 | ## 事件 10 | 11 | ### 事件: 'loaded' 12 | > 触发:**Electron加载其内部预置脚本并开始载入网页或主脚本时** 13 | 14 | 当Node关闭时,预置脚本可以用loaded将 原本已删除的Node全局符号 重新添加回 全局范围: 15 | ```JavaScript 16 | // 预置脚本 17 | const _setImmediate = setImmediate 18 | const _clearImmediate = clearImmediate 19 | process.once('loaded', () => { 20 | global.setImmediate = _setImmediate 21 | global.clearImmediate = _clearImmediate 22 | }) 23 | ``` 24 | 25 | ## 属性 26 | 27 | ### `process.noAsar` 28 | > 用途:**一个用于控制应用程序内的ASAR支持的 `Boolean` ,设置为 `true` 可禁用Node的内置模块中的 `asar`** 29 | 30 | ### `process.type` 31 | > 用途:**返回当前当前进程类型( `String`)** 32 | 33 | 返回值为 `browser` (即主进程) 或 `renderer`(即渲染进程)。 34 | 35 | ### `process.versions.electron` 36 | > 用途:**返回Electron的版本号( `String`)*** 37 | 38 | ### `process.versions.chrome` 39 | > 用途:**返回Chrome的版本号( `String`)*** 40 | 41 | ### `process.resourcesPath` 42 | > 用途:**返回资源目录的路径( `String`)*** 43 | 44 | ### `process.mas` 45 | > 用途:**判断是否Mac App Store app( `Boolean`)*** 46 | 47 | 作为Mac App Store应用(app)运行,该属性为 `true`, 否则为 `undefined`。 48 | 49 | ### `process.windowsStore` 50 | > 用途:**判断是否Windows Store app( `Boolean`)** 51 | 52 | 作为Windows应用商店应用(appx)运行,则此属性为 `true`, 否则为 `undefined`。 53 | 54 | ### `process.defaultApp` 55 | > 用途:**判断是否作为参数传递到默认应用程序启动( `Boolean`)** 56 | 57 | 当 app 在启动时,被作为参数传递给默认应用程序,在主进程中该属性为 `true`, 其他情况均为 `undefined`。 58 | 59 | ## 方法 60 | 61 | ### `process.crash()` 62 | > 用途:**使当前进程的主线程崩溃** 63 | 64 | ### `process.hang()` 65 | > 用途:**使当前进程的主线程挂起** 66 | 67 | ### `process.setFdLimit(maxDescriptors)` _macOS_ _Linux_ 68 | > 用途:**将文件描述符软限制设置为 `maxDescriptors`或OS硬限制,以当前进程的较低者为准** 69 | 70 | * `maxDescriptors` Integer 71 | 72 | ### `process.getProcessMemoryInfo()` 73 | > 用途:**获取有关当前进程内存使用统计信息的对象( `Object`)** 74 | 75 | * `workingSetSize` Integer - 当前固定到实际物理RAM的内存量。 76 | * `peakWorkingSetSize` Integer - 已经固定到实际物理RAM的最大内存量。 77 | * `privateBytes` Integer - 其他进程不共享的内存量,例如JS堆或HTML内容。 78 | * `sharedBytes` Integer - 进程之间共享的内存量,通常是Electron代码本身消耗的内存 79 | 80 | 请注意,所有统计信息都以千字节(KB)为单位。 81 | 82 | ### `process.getSystemMemoryInfo()` 83 | 84 | 返回 `Object`: 85 | * `total` Integer - 系统可用的物理内存总量。 86 | * `free` Integer - 应用程序或磁盘缓存未使用的内存总量。 87 | * `swapTotal` Integer - 系统可用的交换内存总量。 _Windows_ _Linux_ 88 | * `swapFree` Integer - 系统可用的交换内存的自由量。 _Windows_ _Linux_ 89 | 90 | 请注意,所有统计信息都以千字节(KB)为单位。 91 | 92 | 93 | ### `process.getCPUUsage()` 94 | > 用途:**获取处理器使用率( `CPUUsage`)** 95 | 96 | 返回: 97 | * `CPUUsage` [CPUUsage](structures/cpu-usage.md) 98 | 99 | ### `process.getIOCounters()` _Windows_ _Linux_ 100 | > 用途:**获取进程IO占用值( `CPUUsage`)** 101 | 102 | 返回: 103 | * `IOCounters` [IOCounters](structures/io-counters.md) 104 | -------------------------------------------------------------------------------- /api/remote.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:从渲染器进程通信至主进程 2 | 3 | > `remote`模块是一种渲染器进程(网页)和主进程之间通信(IPC)的简单方法。 4 | 5 | 进程: [渲染进程](../glossary.md#渲染进程) 6 | 7 | 在Electron中,GUI相关模块(例如 `dialog`, `menu`等)只能用在主进程而非渲染器进程中使用。 8 | 9 | 为了从渲染器进程使用它们, `ipc`模块是向主进程发送进程间消息所必需的。 10 | 11 | `remote`模块可以调用主进程对象的方法,而类似于Java的[RMI][rmi]无需显式地发送进程间消息。 12 | 13 | 从渲染器进程创建浏览器窗口的示例: 14 | 15 | ```JavaScript 16 | const {BrowserWindow} = require('electron').remote 17 | let win = new BrowserWindow({width: 800, height: 600}) 18 | win.loadURL('https://github.com') 19 | ``` 20 | 21 | **注意:** 对于反向操作(从主进程访问渲染进程),您可以使用[webContents.executeJavascript](web-contents.md#contentsexecutejavascriptcode-usergesture-callback). 22 | 23 | ## 远程对象 24 | 25 | `remote`模块返回的每个对象(包括函数)都代表主进程中的一个对象(我们称之为远程对象或远程函数)。 26 | 27 | 当 调用远程对象的方法 ,执行远程函数 或使用远程构造器(函数)创建新对象 时,其实就是在发送同步的进程间消息。 28 | 29 | 在上面的例子中, `BrowserWindow` 和 `win` 都是远程对象,但 `new BrowserWindow` 并不是在渲染进程中创建 `BrowserWindow` 对象,而是主进程中创建了 `BrowserWindow` 对象,并返回了对应的远程对象( 即 `win` 对象)到渲染进程。 30 | 31 | **注意:**可通过 `remote` 访问的只有首次引用远程对象时出现的[可枚举属性][enumerable-properties]. 32 | 33 | **注意:**当通过 `remote`模块访问时,数组和缓冲区复制在IPC上。在渲染器进程中修改它们不会在主进程中修改它们,反之亦然。 34 | 35 | ## 远程对象的生命周期 36 | 37 | 只要远程对象在渲染进程中生存(换句话说,就是没有被垃圾收集),相应的对象在主进程中就不会被释放。 38 | 39 | 当远程对象被垃圾回收时,主进程中的对应对象才会被取消引用。 40 | 41 | 如果远程对象在渲染器进程中泄漏(例如存储在映射中但从不释放),则主过程中的相应对象也将被泄露,因此您千万不要泄漏远程对象。不过,像字符串和数字这样的主值类型是通过副本发送的。 42 | 43 | ## 将回调传递给主进程 44 | 45 | 您应该非常小心使用此功能,因为主进程中的代码可以接受来自渲染器的回调 - 例如 `remote`模块。 46 | 47 | 首先:为了避免死锁,传递给主进程的回调函数会进行异步调用。所以不能期望主进程获得传递的回调的返回值。 48 | 49 | 比如,你不能主进程中给 `Array.map`传递来自渲染器进程的函数: 50 | 51 | ```JavaScript 52 | // 主进程 mapNumbers.js 53 | exports.withRendererCallback = (mapper) => { 54 | return [1, 2, 3].map(mapper) 55 | } 56 | 57 | exports.withLocalCallback = () => { 58 | return [1, 2, 3].map(x => x + 1) 59 | } 60 | ``` 61 | 62 | 63 | ```JavaScript 64 | // 渲染器进程 65 | const mapNumbers = require('electron').remote.require('./mapNumbers') 66 | const withRendererCb = mapNumbers.withRendererCallback(x => x + 1) 67 | const withLocalCb = mapNumbers.withLocalCallback() 68 | 69 | console.log(withRendererCb, withLocalCb) 70 | // [undefined, undefined, undefined], [2, 3, 4] 71 | ``` 72 | 73 | 如你所见,渲染器回调函数的同步返回值没有按预期产生,并且不匹配主进程中存在的相同回调的返回值。 74 | 75 | 其次,传递给主进程的函数会持续到主进程对他们进行垃圾回收。 76 | 77 | 例如,下面的代码第一眼看上去毫无问题。它为远程对象上的`close`事件绑定了一个回调函数: 78 | 79 | ```JavaScript 80 | require('electron').remote.getCurrentWindow().on('close', () => { 81 | // window was closed... 82 | }) 83 | ``` 84 | 85 | 但是记住回调被主进程引用,直到你明确地卸载它。如果不卸载,每次重新载入窗口都会重新安装,这样每次重新启动时会丢失一个回调。 86 | 87 | 更严重的是,由于以前安装的回调的上下文已经释放,所以当主进程的 `close` 事件触发的时候,会抛出异常。 88 | 89 | 为了避免这个问题,请确保清除对渲染器进行回调并传递给主进程的任何引用。可以清理事件处理程序,或者明确告诉主进程取消来自正在退出的渲染器进程中的回调。 90 | 91 | ## 访问主进程中的内置模块 92 | 93 | 在主进程中的内置模块已经被添加为 `remote`模块中的属性,所以可以直接像使用 `electron`模块一样直接使用它们。 94 | ```JavaScript 95 | const app = require('electron').remote.app 96 | console.log(app) 97 | ``` 98 | 99 | ## 方法 100 | 101 | ### `remote.require(module)` 102 | > 用途:**获取主进程中由 `require(module)` 返回的对象( `any`),并且模块如果是通过相对路径进行指定,则由相对于主进程的入口点进行解析** 103 | 104 | 例如: 105 | 106 | ``` 107 | project/ 108 | ├── main 109 | │ ├── foo.js 110 | │ └── index.js 111 | ├── package.json 112 | └── renderer 113 | └── index.js 114 | ``` 115 | 116 | ```JavaScript 117 | // 主进程: main/index.js 118 | const {app} = require('electron') 119 | app.on('ready', () => { /* ... */ }) 120 | ``` 121 | 122 | ```JavaScript 123 | // 相对模块例子: main/foo.js 124 | module.exports = 'bar' 125 | ``` 126 | 127 | ```JavaScript 128 | // 渲染进程: renderer/index.js 129 | const foo = require('electron').remote.require('./foo') // bar 130 | ``` 131 | 132 | 133 | ### `remote.getCurrentWindow()` 134 | > 用途:**获取此网页的当前窗口([BrowserWindow](browser-window.md))** 135 | 136 | ### `remote.getCurrentWebContents()` 137 | > 用途:**获取此网页的网页内容([WebContents](web-contents.md))** 138 | 139 | ### `remote.getGlobal(name)` 140 | > 用途:**获取主进程中名为 `name` 的全局变量(如 `global[name]`)** 141 | 142 | * `name` String 143 | 144 | ## 属性 145 | 146 | ### `remote.process` 147 | > 属性:**主进程中的 `process` 对象** 148 | 149 | 该属性等同于 `remote.getGlobal('process')` 但是有缓存。 150 | 151 | [rmi]: http://en.wikipedia.org/wiki/Java_remote_method_invocation 152 | [enumerable-properties]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties -------------------------------------------------------------------------------- /api/sandbox-option.md: -------------------------------------------------------------------------------- 1 | # `sandbox` 沙盒选项 2 | 3 | >创建一个渲染器可运行于 Chromium OS 沙盒中的浏览器窗口. 启用此选项后,渲染器必须通过IPC与主进程进行通信才能访问Node API。同时,为了使Chromium OS沙盒可运行,electron 必须使用 `--enable-sandbox`命令行参数运行。 4 | 5 | Chromium主要的安全功能之一是所有Blink渲染或JavaScript都运行在沙盒中,该沙盒使用了特定于操作系统的功能以确保渲染器进程不会对系统造成危害. 6 | 7 | 也就是说,启用沙盒时,渲染器只能通过IPC将任务委托给主进程来对系统进行更改。详情参考[chromium沙盒文档](https://www.chromium.org/developers/design-documents/sandbox) 8 | 9 | 因为Electron的主要特性是可在渲染器进程中运行node.js(以便使用web技术轻松开发应用),所以Electron默认禁用了沙盒, 10 | 11 | 之所以这样,是因为大多数的node.js API都需要使用系统访问权限,比如 `require()`缺少了系统访问权限则无法使用, 但在沙盒环境中这样做是被禁止的. 12 | 13 | 通常,引起这样的情况并不是由于桌面应用程序本身的问题,而是代码之间的可靠和依赖性使Electron在安全性上不像Chromium可显示不受信任的Web内容. 14 | 15 | 对于需要更安全性的应用程序, `sandbox`会强制electron使用基础的chromium渲染器以便兼容沙盒. 16 | 17 | 沙盒渲染器即没有运行node.js环境也不会将node.js的JavaScript API发布到客户端代码中更不会修改任何默认的JavaScript API,但有个例外是预加载脚本可访问Electron渲染器API子集. 18 | 19 | 综上所述,诸如`window.open`之类的API会是和chromium一样的运作方式(即它们不返回 `BrowserWindowProxy`) 20 | 21 | ## 例子 22 | 23 | 在`webPreferences`中设置`sandbox:true`即可创建一个沙盒窗口: 24 | 25 | ```js 26 | let win 27 | app.on('ready', () => { 28 | win = new BrowserWindow({ 29 | webPreferences: { 30 | sandbox: true 31 | } 32 | }) 33 | w.loadURL('http://google.com') 34 | }) 35 | ``` 36 | 37 | 上面代码中,用于创建 `BrowserWindow` 的node.js是禁用的,只能通过IPC进行通信.使用该选项可阻止electron在渲染器中创建 `node.js runtime`. 38 | 39 | 另外,在这个新窗口中, `window.open`将遵循默认的原生行为即electron创建一个 `BrowserWindow` 并通过 `window.open`返回一个 `proxy`. 40 | 41 | 还有,此选项本身不会启动操作系统自带的OS沙盒.需要将 `--enable-sandbox`命令行参数传递给electron( 即 `app.commandLine.appendSwitch('--enable-sandbox')` )才可启用该功能,该参数将对所有的 `BrowserWindow` 实例强制设置 `sandbox: true`. 42 | 43 | ```js 44 | let win 45 | app.on('ready', () => { 46 | // 启用了`--enable-sandbox`就无需设置`sandbox: true` . 47 | win = new BrowserWindow() 48 | w.loadURL('http://google.com') 49 | }) 50 | ``` 51 | 52 | 请注意,对chromium沙盒的设置进行了更改之后,electron/node启动运行时除了调用 `app.commandLine.appendSwitch('--enable-sandbox')`,还需要执行下列命令行: 53 | 54 | ``` 55 | electron --enable-sandbox app.js 56 | ``` 57 | 58 | 一旦启用了 `--enable-sandbox`参数,则无法使OS沙盒仅对某些渲染器生效,也就是无法创建普通的electron窗口. 59 | 60 | 如果需要在应用中混合使用沙盒和非沙盒渲染器,那么你只需忽略 `--enable-sandbox`这个参数,但是没有它,用 `sandbox:true`创建的窗口仍然被禁用node.js ,还是只能通过IPC进行通信,IPC本身已经是安全POV的增益。 61 | 62 | ## 预加载脚本 63 | 64 | 应用程序使用预加载脚本自定义沙盒渲染器: 65 | 66 | ```js 67 | let win 68 | app.on('ready', () => { 69 | win = new BrowserWindow({ 70 | webPreferences: { 71 | sandbox: true, 72 | preload: 'preload.js' 73 | } 74 | }) 75 | w.loadURL('http://google.com') 76 | }) 77 | ``` 78 | 79 | preload.js: 80 | 81 | ```js 82 | // 每次创建javascript上下文时都会加载这个文件,它仅运行在可访问Electron渲染器子集的局部范围中,你务必 83 | //小心谨慎的使任何内容都不影响至全局范围中. 84 | const fs = require('fs') 85 | const {ipcRenderer} = require('electron') 86 | 87 | // 使用`fs`模块读取配置文件 88 | const buf = fs.readFileSync('allowed-popup-urls.json') 89 | const allowedUrls = JSON.parse(buf.toString('utf8')) 90 | 91 | const defaultWindowOpen = window.open 92 | 93 | function customWindowOpen (url, ...args) { 94 | if (allowedUrls.indexOf(url) === -1) { 95 | ipcRenderer.sendSync('blocked-popup-notification', location.origin, url) 96 | return null 97 | } 98 | return defaultWindowOpen(url, ...args) 99 | } 100 | 101 | window.open = customWindowOpen 102 | ``` 103 | 104 | 预载脚本中要注意的重要事项: 105 | 106 | - 即使沙盒渲染器未运行node.js,它也可访问 `Buffer`, `process`, `setImmediate` 和 `require`等类似node的环境. 107 | - 预加载脚本可由 `remote`和 `ipcRenderer`模块进行间接访问主进程中的所有API。 这就是 `fs`(上面使用的)和其他模块的实现方法:它们是主进程中的远程对等体的代理。 108 | - 预加载脚本必须包含在一个单独的脚本中,但是你可以使用类似browserify之类的工具来合并含有多个模块的复杂预加载脚本.实际上,electron已使用了browserify为preload脚本提供类似node的环境. 109 | 110 | 使用以下内容创建一个browserify包,并将其当成预加载脚本的例子: 111 | 112 | browserify preload/index.js \ 113 | -x electron \ 114 | -x fs \ 115 | --insert-global-vars=__filename,__dirname -o preload.js 116 | 117 | 详解: 118 | 119 | - `-x` 应该和预加载范围中已暴露的任何必须模块一起使用.并告知browserify使用封装的 `require`方法. 120 | - `--insert-global-vars` 将确保 `process`, `Buffer` 和 `setImmediate`取自封闭的范围内(通常这个范围是指browserify注入代码). 121 | 122 | 目前在 `preload` 范围中提供的 `require`方法有以下模块: 123 | 124 | - `child_process` 125 | - `electron` (crashReporter, remote and ipcRenderer) 126 | - `fs` 127 | - `os` 128 | - `timers` 129 | - `url` 130 | 131 | 你也可以按需添加更多内容来实现在沙盒中暴露更多的电子API,而且主进程中的任何模块都可以通过`electron.remote.require`使用。 132 | 133 | ## 现状 134 | 135 | `sandbox`设置目前还是个实验性功能,所以需要谨慎使用,因为我们仍然不知道将electron渲染器API暴露给预加载脚本有什么样的安全隐患. 136 | 137 | 当渲染那些不受信任的内容前,请考虑以下事项: 138 | - 预加载脚本可能会将某些特性API泄露给不受信任的代码. 139 | - 恶意代码可利用V8引擎中的某些bug访问渲染器预加载API并通过 `remote`模块完全访问系统. 140 | 141 | 在electron中显示不受信任的内容和将预加载API暴露在沙盒中的行为目前还是很不稳定和不安全的,我们目前正在积极改善中. 142 | 143 | 有个简单的大幅提高安全性的方法是默认阻止来自沙盒渲染器的IPC消息,或在主进程标明可允许的内容. -------------------------------------------------------------------------------- /api/screen.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:screen(检索屏幕信息) 2 | 3 | > `screen` 模块用于检索有关屏幕大小,显示,光标位置等的信息 4 | 进程: [主进程](../glossary.md#主进程) [渲染进程](../glossary.md#渲染进程) 5 | 6 | `screen` 是一个 [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). 7 | 8 | **注意:** `app`模块必须用在 `ready`事件后. 9 | 10 | **注意:** 在渲染进程或开发者工具栏中, `window.screen` 是一个预设值的 DOM属性, 所以 `var screen = require('electron').screen` 这样写的话是无效的. 11 | 12 | 创建一个全屏窗口的例子 : 13 | 14 | ```JavaScript 15 | const electron = require('electron') 16 | const {app, BrowserWindow} = electron 17 | 18 | let win 19 | 20 | app.on('ready', () => { 21 | const {width, height} = electron.screen.getPrimaryDisplay().workAreaSize 22 | win = new BrowserWindow({width, height}) 23 | win.loadURL('https://github.com') 24 | }) 25 | ``` 26 | 27 | 在外部显示器中创建窗口的另一个示例: 28 | ```JavaScript 29 | const electron = require('electron') 30 | const {app, BrowserWindow} = require('electron') 31 | 32 | let win 33 | 34 | app.on('ready', () => { 35 | let displays = electron.screen.getAllDisplays() 36 | let externalDisplay = displays.find((display) => { 37 | return display.bounds.x !== 0 || display.bounds.y !== 0 38 | }) 39 | 40 | if (externalDisplay) { 41 | win = new BrowserWindow({ 42 | x: externalDisplay.bounds.x + 50, 43 | y: externalDisplay.bounds.y + 50 44 | }) 45 | win.loadURL('https://github.com') 46 | } 47 | }) 48 | ``` 49 | ## `Display` 对象 50 | 51 | `Display`对象表示连接到系统的物理显示器。虚拟 `Display` 可以存在于无头系统上, `Display` 也可以是对应于远程的虚拟显示器。 52 | * `display` object 53 | * `id` Integer - 与显示相关联的唯一标识符。 54 | * `rotation` Integer - 可选 `0`, `1`, `2`, `3`, 每个代表顺时针方向的屏幕旋转角度, 可选 `0`, `90`, `180`, `270`。 55 | * `scaleFactor` Number -输出设备的像素比例因子。 56 | * `touchSupport` String - 是否支持触摸,可选 `available`, `unavailable`, `unknown`. 57 | * `bounds` Object [Rectangle](rectangle.md) 58 | * `size` Object 59 | * `height` Number 60 | * `width` Number 61 | * `workArea` [Rectangle](rectangle.md) 62 | * `workAreaSize` Object 63 | * `height` Number 64 | * `width` Number 65 | 66 | ## 事件 67 | 68 | ### 事件: 'display-added' 69 | > 触发:**添加 `newDisplay`显示器时** 70 | 71 | * `event` Event 72 | * `newDisplay` [Display](structures/display.md) 73 | 74 | ### 事件: 'display-removed' 75 | > 触发:**移除 `oldDisplay`显示器时** 76 | 77 | * `event` Event 78 | * `oldDisplay` [Display](structures/display.md) 79 | 80 | ### 事件: 'display-metrics-changed' 81 | > 触发:**更改 `display` 中的一个或多个度量时** 82 | 83 | * `event` Event 84 | * `display` [Display](structures/display.md) 85 | * `changedMetrics` String[] 描述变化的字符串数组。可选 `bounds`, `workArea`, `scaleFactor`和 `rotation`。 86 | 87 | ## 方法 88 | 89 | ### `screen.getCursorScreenPoint()` 90 | 91 | > 用途:**获取当前鼠标指针坐标( `Object`)** 92 | 93 | * `x` Integer 94 | * `y` Integer 95 | 96 | ### `screen.getPrimaryDisplay()` 97 | > 用途:**获取当前主显示屏([`Display`](structures/display.md))** 98 | 99 | ### `screen.getAllDisplays()` 100 | > 用途:**获取所有可用显示屏组成的数组([`Display`](structures/display.md))** 101 | 102 | ### `screen.getDisplayNearestPoint(point)` 103 | > 用途:**获取离指定点最近的显示屏([`Display`](structures/display.md))** 104 | 105 | * `point` Object 106 | * `x` Integer 107 | * `y` Integer 108 | 109 | ### `screen.getDisplayMatching(rect)` 110 | > 用途:**获取与提供的边界最接近的显示屏([`Display`](structures/display.md))** 111 | 112 | * `rect` [Rectangle](structures/rectangle.md) -------------------------------------------------------------------------------- /api/shell.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:shell(使用系统默认应用程序管理文件或URL) 2 | 3 | > `shell`模块提供与 桌面集成 相关的功能,如点击url时调用默认浏览器 4 | 5 | 进程: [主进程](../glossary.md#主进程), [渲染进程](../glossary.md#渲染进程) 6 | 7 | 使用默认浏览器打开链接: 8 | ```JavaScript 9 | const {shell} = require('electron') 10 | shell.openExternal('https://github.com') 11 | ``` 12 | 13 | ## 方法 14 | 15 | ### `shell.showItemInFolder(fullPath)` 16 | > 用途:**判断是否在文件管理器中显示并选中指定文件( `Boolean`)** 17 | 18 | * `fullPath` String 19 | 20 | ### `shell.openItem(fullPath)` 21 | > 用途:**判断是否用默认程序打开指定文件( `Boolean`)** 22 | 23 | * `fullPath` String 24 | 25 | ### `shell.openExternal(url[, options, call,back])` 26 | > 用途:**判断链接是否关联的默认程序打开,如`mailto:`以邮件程序打开( `Boolean`)** 27 | 28 | * `url` String 29 | * `options` Object (可选) _macOS_ 30 | * `activate` Boolean - `true`将打开默认应用程序。默认值为 `true`。 31 | * `callback` Function (可选) -指定后将执行异步打开. _macOS_ 32 | * `error` Error 33 | 34 | ### `shell.moveItemToTrash(fullPath)` 35 | > 用途:**判断是否将指定项目扔到回收站( `Boolean`)** 36 | 37 | * `fullPath` String 38 | 39 | ### `shell.beep()` 40 | > 用途:**播放蜂鸣声** 41 | 42 | ### `shell.writeShortcutLink(shortcutPath[, operation], options)` _Windows_ 43 | > 用途:**判断是否成功创建或更新,覆盖快捷方式( `Boolean`)** 44 | 45 | * `shortcutPath` String 46 | * `operation` String (可选) - 操作方式,默认为 `create`,可选: 47 | * `create` - 创建新的快捷方式,已存在则覆盖。 48 | * `update` -仅在现有快捷方式上更新指定的属性 49 | * `replace` - 覆盖现有快捷方式,如果快捷方式不存在则失败。 50 | * `options` [ShortcutDetails](structures/shortcut-details.md) 51 | 52 | ### `shell.readShortcutLink(shortcutPath)` _Windows_ 53 | > 用途:**读取链接至指定路径 `shortcutPath`的快捷方式( ` [`ShortcutDetails`](structures/shortcut-details.md)`)** 54 | 55 | * `shortcutPath` String 56 | 57 | 发生任何错误时将抛出异常。 -------------------------------------------------------------------------------- /api/structures/README.md: -------------------------------------------------------------------------------- 1 | # 结构列表 2 | * [蓝牙设备对象](bluetooth-device.md) 3 | * [证书对象](certificate-principal.md) 4 | * [证书主体对象](certificate.md) 5 | * [Cookie对象](cookie.md) 6 | * [崩溃报告对象](crash-report.md) 7 | * [桌面捕获源对象](desktop-capturer-source.md) 8 | * [显示器对象](display.md) 9 | * [打印机信息对象](printer-info.md) 10 | * [文件过滤器对象](file-filter.md) 11 | * [最近使用的项目](jump-list-category.md) 12 | * [常用列表项](jump-list-item.md) 13 | * [CPU使用率对象即程序占用的CPU资源](cpu-usage.md) 14 | * [IO值对象](io-counters.md) 15 | * [内存信息对象](memory-info.md) 16 | * [进程内存信息对象](process-memory-info.md) 17 | * [内存使用详细信息](memory-usage-details.md) 18 | * [Mime类型缓冲区](mime-typed-buffer.md) 19 | * [矩形对象](rectangle.md) 20 | * [删除客户端证书对象](remove-client-certificate.md) 21 | * [删除密码对象](remove-password.md) 22 | * [Scrubber项对象](scrubber-item.md) 23 | * [分段控制对象](segmented-control-segment.md) 24 | * [快捷方式对象](shortcut-details.md) 25 | * [任务对象](task.md) 26 | * [缩略图工具栏按钮对象](thumbar-button.md) 27 | * [上传blob对象](upload-blob.md) 28 | * [上传数据对象](upload-data.md) 29 | * [上传文件系统对象](upload-file-system.md) 30 | * [上传文件对象](upload-file.md) 31 | * [上传原始数据对象](upload-raw-data.md) -------------------------------------------------------------------------------- /api/structures/bluetooth-device.md: -------------------------------------------------------------------------------- 1 | # BluetoothDevice Object (蓝牙设备对象) 2 | 3 | * `deviceName` String 4 | * `deviceId` String 5 | -------------------------------------------------------------------------------- /api/structures/certificate-principal.md: -------------------------------------------------------------------------------- 1 | # CertificatePrincipal Object(证书主体对象) 2 | 3 | * `commonName` String - 公用名 4 | * `organizations` String [] - 组织名称 5 | * `organizationUnits` String [] - 组织单元名称 6 | * `locality` String - Locality 7 | * `state` String - 州或省 8 | * `country` String - 国家或地区 -------------------------------------------------------------------------------- /api/structures/certificate.md: -------------------------------------------------------------------------------- 1 | # Certificate Object( 证书对象) 2 | 3 | * `data` String - PEM编码数据 4 | * `issuer` [CertificatePrincipal](certificate-principal.md) - 发行人主体 5 | * `issuerName` String - 发行商的公用名 6 | * `issuerCert`证书 - 颁发者证书(如果不是自签名) 7 | * `subject` [CertificatePrincipal](certificate-principal.md) - 主题主体 8 | * `subjectName` String - 主题公共名 9 | * `serialNumber` String - 十六进制值表示字符串 10 | * `validStart` Number - 证书的有效起始日期(以秒为单位) 11 | * `validExpiry` Number - 证书的有效结束日期(以秒为单位) 12 | * `fingerprint` String - 证书的指纹 -------------------------------------------------------------------------------- /api/structures/cookie.md: -------------------------------------------------------------------------------- 1 | # Cookie Object(Cookie对象) 2 | 3 | * `name` String - cookie的名称。 4 | * `value` String - Cookie的值。 5 | * `domain` String(可选) - Cookie的域。 6 | * `hostOnly` Boolean(可选) - Cookie是否为仅限主机的Cookie。 7 | * `path` String(可选) - Cookie的路径。 8 | * `secure` Boolean(可选) - Cookie是否标记为安全。 9 | * `httpOnly` Boolean(可选) - cookie是否标记为仅HTTP。 10 | * `session` Boolean(可选) - Cookie是会话cookie还是具有到期日期的持久Cookie。 11 | * `expirationDate` Double(可选) - Cookie的到期日期(秒级),session cookies可忽略该项 -------------------------------------------------------------------------------- /api/structures/cpu-usage.md: -------------------------------------------------------------------------------- 1 | # CPUUsage Object(CPU使用率对象即程序占用的CPU资源) 2 | 3 | * `percentCPUUsage` Number - 上一次调用getCPUUsage之后使用的CPU占比。 4 | * `idleWakeupsPerSecond` Number - 上一次调用getCPUUsage之后每秒钟的平均空闲cpu唤醒次数。 5 | 6 | 以上两个参数首次获取均默认返回 `0`. -------------------------------------------------------------------------------- /api/structures/crash-report.md: -------------------------------------------------------------------------------- 1 | # CrashReport Object(崩溃报告对象) 2 | 3 | * `date` String 4 | * `ID` Integer -------------------------------------------------------------------------------- /api/structures/desktop-capturer-source.md: -------------------------------------------------------------------------------- 1 | # DesktopCapturerSource Object(桌面捕获源对象) 2 | 3 | * `id` String - 调用[`navigator.webkitGetUserMedia`]时可用作 `chromeMediaSourceId`约束的窗口或屏幕的标识符。 4 | 标识符的格式为 `window:XX`或 `screen:XX`,其中 `XX`是一个随机生成的数字。 5 | * `name` String - 屏幕源将被命名为 `Entire Screen` 或 `Screen `,而窗口源的名称将匹配窗口标题。 6 | * `thumbnail` [NativeImage](../ native-image.md) - 缩略图。 7 | 8 | **注意:**不能保证缩略图的大小与传递给 `desktopCapturer.getSources`的 `options`中指定的 `thumbnailSize`相同。 9 | 10 | 实际大小取决于屏幕或窗口的比例。 -------------------------------------------------------------------------------- /api/structures/display.md: -------------------------------------------------------------------------------- 1 | # Display Object(显示器对象) 2 | 3 | * `id` Number - 与显示相关联的唯一标识符。 4 | * `rotation`Number -顺时针方向的屏幕旋转角度, 可选`0`,`90`,`180`,`270`。 5 | * `scaleFactor` Number - 输出设备的像素比例因子。 6 | * `touchSupport` String - 是否支持触摸,可选 `available`, `unavailable`, `unknown`. 7 | * `bounds` Object [Rectangle](rectangle.md) 8 | * `size` Object 9 | * `height` Number 10 | * `width` Number 11 | * `workArea` [Rectangle](rectangle.md) 12 | * `workAreaSize` Object 13 | * `height` Number 14 | * `width` Number 15 | 16 | `Display`对象表示连接到系统的物理显示器。虚拟 `Display` 可以存在于无头系统上, `Display` 也可以是对应于远程的虚拟显示器。 -------------------------------------------------------------------------------- /api/structures/file-filter.md: -------------------------------------------------------------------------------- 1 | # FileFilter Object(文件过滤器对象) 2 | 3 | * `name` String 4 | * `extensions` String[] 5 | -------------------------------------------------------------------------------- /api/structures/io-counters.md: -------------------------------------------------------------------------------- 1 | # IOCounters Object(IO值对象) 2 | 3 | * `readOperationCount` Number - I/O读操作的数量. 4 | * `writeOperationCount` Number - I/O写操作的数量. 5 | * `otherOperationCount` Number - I/O其它读写操作的数量. 6 | * `readTransferCount` Number - I/O读取传输的次数. 7 | * `writeTransferCount` Number - I/O写入传输的次数. 8 | * `otherTransferCount` Number - I/O其它读写传输的次数. -------------------------------------------------------------------------------- /api/structures/jump-list-category.md: -------------------------------------------------------------------------------- 1 | # JumpListCategory Object( 最近使用的项目) 2 | 3 | * `type` String(可选) - 以下之一: 4 | * `tasks` - 此类别中的项目将被放置到标准的 `Tasks` 类别中。只能有一个这样的类别而且总是显示在跳转列表的底部。 5 | * `frequent` - 显示由应用程序频繁打开的文件的列表,类别的名称及其项目由Windows设置。 6 | * `recent` - 显示由应用程序最近打开的文件的列表,类别的名称及其项目由Windows设置。项目可以使用`app.addRecentDocument(path)`间接添加到此类别。 7 | * `custom` - 显示任务或文件链接, `name`必须由应用程序设置。 8 | * `name` String(可选) - 如果 `type`是 `custom`,则必须设置,否则应该省略。 9 | * `items` JumpListItem [](可选) - [`JumpListItem`](jump-list-item.md) 对象的数组,如果 `type`不是 `tasks`或 `custom`则忽略 10 | 11 | **注意:** 12 | 13 | 如果 `JumpListCategory`对象没有 `type`和 `name`属性,那么它的 `type`被假定为 `tasks`。 14 | 15 | 如果设置了 `name`属性,但省略了 `type`属性,则 `type`被假定为 `custom`。 -------------------------------------------------------------------------------- /api/structures/jump-list-item.md: -------------------------------------------------------------------------------- 1 | # JumpListItem Object(常用列表项) 2 | 3 | * `type` String(可选) - 以下之一: 4 | * `task` - 启动具有特定参数的应用程序的任务。 5 | * `separator` - 用来分隔标准 `Tasks`类别中的项目。 6 | * `file` - 使用创建常用列表的应用程序打开的文件链接,为了这个工作应用程序必须注册为文件类型的处理程序(尽管它不必是默认处理程序) 。 7 | * `path` String(可选) - 要打开的文件的路径, `type`是 `file`时才应该设置。 8 | * `program` String(可选) - 要执行的程序的路径,通常你应该指定` process.execPath`打开当前程序。`type`是 `task`时才应该设置。 9 | * `args` String(可选) - 执行 `program`时的命令行参数。`type`是 `task`时才应该设置。 10 | * `title` String(可选) - 要在常用列表中显示的项目文本。`type`是 `task`时才应该设置。 11 | * `description` String(可选) - 任务描述(显示在工具提示中)。`type`是 `task`时才应该设置。 12 | * `iconPath` String(可选) - 要在常用列表中显示的图标的绝对路径,它可以是包含图标的任意资源文件(例如 `.ico`, `.exe`, `.dll`)。你通常可以指定 `process.execPath`来显示程序图标。 13 | * `iconIndex` Number(可选) - 资源文件中图标的索引。如果资源文件包含多个图标,则此值可用于指定应为此任务显示的图标的从零开始的索引。如果资源文件只包含一个图标,则此属性应设置为`0`。 -------------------------------------------------------------------------------- /api/structures/memory-info.md: -------------------------------------------------------------------------------- 1 | # MemoryInfo Object(内存信息对象) 2 | 3 | * `pid` Integer - 进程id 4 | * `workingSetSize` Integer - 当前固定在实际物理RAM中的内存量 5 | * `peakWorkingSetSize` Integer - 已经被固定到实际物理RAM的最大内存量 6 | * `privateBytes` Integer - 其他进程不共享的内存量,如JS或HTML内容 7 | * `sharedBytes` Integer - 进程之间共享的内存量,通常是Electron代码本身消耗的内存 8 | 9 | 注意,所有单位以Kb为单位 -------------------------------------------------------------------------------- /api/structures/memory-usage-details.md: -------------------------------------------------------------------------------- 1 | # MemoryUsageDetails Object(内存使用详细信息) 2 | 3 | * `count` Number 4 | * `size` Number 5 | * `liveSize` Number -------------------------------------------------------------------------------- /api/structures/mime-typed-buffer.md: -------------------------------------------------------------------------------- 1 | # MimeTypedBuffer Object(Mime类型缓冲区) 2 | 3 | * `mimeType` String - 要发送的缓冲区的mimeType 4 | * `data` Buffer - 实际的Buffer内容 5 | -------------------------------------------------------------------------------- /api/structures/printer-info.md: -------------------------------------------------------------------------------- 1 | # 打印机信息对象 Object 2 | 3 | * `name` String - 名称 4 | * `description` String - 描述 5 | * `status` Number - 状态 6 | * `isDefault` Boolean - 是否默认打印机 7 | * `options` Object - 附加字段 8 | 9 | 例子: 10 | ```javascript 11 | name: 'Zebra_LP2844', 12 | description: 'Zebra LP2844', 13 | status: 3, 14 | isDefault: false, 15 | options: { 16 | copies: '1', 17 | 'device-uri': 'usb://Zebra/LP2844?location=14200000', 18 | finishings: '3', 19 | 'job-cancel-after': '10800', 20 | 'job-hold-until': 'no-hold', 21 | 'job-priority': '50', 22 | 'job-sheets': 'none,none', 23 | 'marker-change-time': '0', 24 | 'number-up': '1', 25 | 'printer-commands': 'none', 26 | 'printer-info': 'Zebra LP2844', 27 | 'printer-is-accepting-jobs': 'true', 28 | 'printer-is-shared': 'true', 29 | 'printer-location': '', 30 | 'printer-make-and-model': 'Zebra EPL2 Label Printer', 31 | 'printer-state': '3', 32 | 'printer-state-change-time': '1484872644', 33 | 'printer-state-reasons': 'offline-report', 34 | 'printer-type': '36932', 35 | 'printer-uri-supported': 'ipp://localhost/printers/Zebra_LP2844', 36 | system_driverinfo: 'Z' 37 | } 38 | }] 39 | ``` -------------------------------------------------------------------------------- /api/structures/process-memory-info.md: -------------------------------------------------------------------------------- 1 | # ProcessMemoryInfo Object(进程内存信息对象) 2 | 3 | * `pid` Integer - 进程ID 4 | * `memory` [MemoryInfo](memory-info.md) - 进程的内存信息 -------------------------------------------------------------------------------- /api/structures/rectangle.md: -------------------------------------------------------------------------------- 1 | # Rectangle Object(矩形对象) 2 | 3 | * `x` Number - 矩形原点的x坐标 4 | * `y` Number - 矩形原点的y坐标 5 | * `width` Number 6 | * `height` Number 7 | -------------------------------------------------------------------------------- /api/structures/remove-client-certificate.md: -------------------------------------------------------------------------------- 1 | # RemoveClientCertificate Object(删除客户端证书对象) 2 | 3 | * `type` String - `clientCertificate`. 4 | * `origin` String - 必须从缓存中删除相关客户端证书的服务器的来源。 -------------------------------------------------------------------------------- /api/structures/remove-password.md: -------------------------------------------------------------------------------- 1 | # RemovePassword Object(删除密码对象) 2 | 3 | * `type` String - `password`。 4 | * `origin` String(可选) - 当提供时,与原始相关的认证信息将被删除,否则整个缓存会被清除。 5 | * `scheme` String(可选) - 认证方案。可选 `basic`, `digest`, `ntlm`, `negotiate`。如果通过 `origin`删除,必须提供。 6 | * `realm` String(可选) - 认证的领域。如果通过 `origin`删除,必须提供。 7 | * `username` String(可选) - 认证的凭证。如果通过 `origin`删除,必须提供。 8 | * `password` String(可选) - 认证的凭证。如果通过 `origin`删除,必须提供。 -------------------------------------------------------------------------------- /api/structures/scrubber-item.md: -------------------------------------------------------------------------------- 1 | # ScrubberItem Object(Scrubber项对象) 2 | 3 | * `label` String - (可选) 项文本 4 | * `icon` NativeImage - (可选) 项图标 -------------------------------------------------------------------------------- /api/structures/segmented-control-segment.md: -------------------------------------------------------------------------------- 1 | # SegmentedControlSegment Object(分段控制对象) 2 | 3 | * `label` String - (Optional) 出现在此段中的文本 4 | * `icon` NativeImage - (Optional) 出现在此段中的图像 5 | * `enabled` Boolean - (Optional) 此段是否可选。 默认值 `true` -------------------------------------------------------------------------------- /api/structures/shortcut-details.md: -------------------------------------------------------------------------------- 1 | # ShortcutDetails Object(快捷方式对象) 2 | 3 | * `target` String - 从这个快捷方式启动的目标。 4 | * `cwd` String(可选) - 工作目录。默认值为空。 5 | * `args` String(可选) - 从此快捷方式启动时应用于`target'的参数。默认值为空。 6 | * `description` String(可选) - 快捷方式的描述。默认值为空。 7 | * `icon` String(可选) - 图标的路径,可以是DLL或EXE。 `icon`和`iconIndex`必须设置在一起。默认值为空,它使用目标的图标。 8 | * `iconIndex` Number(可选) - 当`icon`是DLL或EXE时,图标的资源ID。默认值为0。 9 | * `appUserModelId` String(可选) - 应用程序用户模型ID。默认值为空。 -------------------------------------------------------------------------------- /api/structures/task.md: -------------------------------------------------------------------------------- 1 | # Task Object(任务对象) 2 | 3 | * `program` String - 要执行的程序的路径,通常你应该指定`process.execPath`打开当前程序。 4 | * `arguments` String - 执行`program`时的命令行参数。 5 | * `title` String - 要在JumpList中显示的字符串。 6 | * `description` String - 此任务的描述。 7 | * `iconPath` String - 要在JumpList中显示的图标的绝对路径,它可以是包含图标的任意资源文件。你通常可以指定`process.execPath`来显示程序的图标。 8 | * `iconIndex` Number - 图标文件中的图标索引。如果图标文件由两个或多个图标组成,请设置此值以标识图标。如果图标文件由一个图标组成,则此值为0。 -------------------------------------------------------------------------------- /api/structures/thumbar-button.md: -------------------------------------------------------------------------------- 1 | # ThumbarButton Object(缩略图工具栏按钮对象) 2 | 3 | * `icon` [NativeImage](../native-image.md)- 缩略图工具栏中显示的icon图标。 4 | * `click`Function 5 | * `tooltip` String(可选) - 按钮的提示文本。 6 | * `flags` String [](可选) - 控制按钮的特定状态和行为。默认情况下,它是`['enabled']`。 7 | 8 | `flags`是一个数组,可以包括以下 `String`: 9 | * `enabled` - 该按钮是活动的,可供用户使用。 10 | * `disabled` - 该按钮被禁用。如变灰等无法响应动作的外观。 11 | * `dismissonclick` - 当点击按钮时,缩略图窗口立即关闭。 12 | * `nobackground` - 不要绘制按钮边框,只使用图像。 13 | * `hidden` - 该按钮不向用户显示。 14 | * `noninteractive` - 按钮不是交互式也不绘制按下的状态。常用在通知中使用的按钮。 -------------------------------------------------------------------------------- /api/structures/upload-blob.md: -------------------------------------------------------------------------------- 1 | # UploadBlob Object(上传blob对象) 2 | 3 | * `type` String - `blob`. 4 | * `blobUUID` String - 要上传的blob数据的UUID。 5 | -------------------------------------------------------------------------------- /api/structures/upload-data.md: -------------------------------------------------------------------------------- 1 | # UploadData Object(上传数据对象) 2 | 3 | * `bytes` Buffer - 发送的内容。 4 | * `file` String - 要上传的文件的路径。 5 | * `blobUUID` String - Blob数据的UUID。通过 [ses.getBlobData](../session.md#sesgetblobdataidentifier-callback) 方法来接收数据, 6 | -------------------------------------------------------------------------------- /api/structures/upload-file-system.md: -------------------------------------------------------------------------------- 1 | # UploadFileSystem Object(上传文件系统对象) 2 | 3 | * `type` String - `fileSystem`. 4 | * `filsSystemURL` String - 进行读取上传数据的文件系统URL。 5 | * `offset` Integer - 默认为`0`。 6 | * `length` Integer - 从 `offset`读取的字节数。默认为`0'。 7 | * `modificationTime` Double - 秒级的最后修改时间 -------------------------------------------------------------------------------- /api/structures/upload-file.md: -------------------------------------------------------------------------------- 1 | # UploadFile Object(上传文件对象) 2 | 3 | * `type` String - `file`。 4 | * `filePath` String - 要上传的文件的路径。 5 | * `offset` Integer - 默认为`0`。 6 | * `length` Integer - 从 `offset`读取的字节数。默认为`0'。 7 | * `modifyTime` Double - 秒级的最后修改时间 -------------------------------------------------------------------------------- /api/structures/upload-raw-data.md: -------------------------------------------------------------------------------- 1 | # UploadRawData Object(上传原始数据对象) 2 | 3 | * `type` String - `rawData`. 4 | * `bytes` Buffer - 要上传的数据。 5 | -------------------------------------------------------------------------------- /api/synopsis.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:开发概要 2 | > 如何使用Node.js和Electron API. 3 | 4 | 所有的[Node.js的内置模块](https://nodejs.org/api/)都可以完美运用于Electron和第三方Node模块中(包括[native modules](../tutorial/using-node-node-modules.md))。 5 | 6 | Electron还为开发本地桌面应用程序提供了一些额外的内置模块。有些仅在主进程中或渲染器进程(网页)中可用,有的则通用于两个进程。 7 | 8 | 基本规则:GUI模块或者系统底层的模块只能在主进程中使用。 9 | 10 | 要使用这些模块,你必须熟稔[主进程vs渲染进程](../tutorial/quick-start.md#main-process)。 11 | 12 | 像普通Node.js一样的主进程脚本: 13 | ```JavaScript 14 | const {app, BrowserWindow} = require('electron') 15 | let win = null 16 | 17 | app.on('ready', () => { 18 | win = new BrowserWindow({width: 800, height: 600}) 19 | win.loadURL('https://github.com') 20 | }) 21 | ``` 22 | 23 | 渲染进程和传统的web界面一样,除了它具有使用node模块的能力: 24 | 25 | ```html 26 | 27 | 28 | 29 | 33 | 34 | 35 | ``` 36 | 37 | 如果想运行应用,请参考 [运行应用程序](../tutorial/quick-start.md#run-your-app). 38 | 39 | ## 解构任务 40 | 从0.37版本起,你可以使用[解构赋值][destructuring-assignment]更简便的使用内置模块。 41 | 42 | ```JavaScript 43 | const {app, BrowserWindow} = require('electron') 44 | let win 45 | app.on('ready', () => { 46 | win = new BrowserWindow() 47 | win.loadURL('https://github.com') 48 | }) 49 | ``` 50 | 51 | 只需把模块引入( `require`)并解构至 `electron`中即可使用: 52 | ```JavaScript 53 | const electron = require('electron') 54 | const {app, BrowserWindow} = electron 55 | 56 | let win 57 | 58 | app.on('ready', () => { 59 | win = new BrowserWindow() 60 | win.loadURL('https://github.com') 61 | }) 62 | ``` 63 | 上面等同下面的代码: 64 | ```JavaScript 65 | const electron = require('electron') 66 | const app = electron.app 67 | const BrowserWindow = electron.BrowserWindow 68 | let win 69 | 70 | app.on('ready', () => { 71 | win = new BrowserWindow() 72 | win.loadURL('https://github.com') 73 | }) 74 | ``` 75 | 76 | [gui]: https://en.wikipedia.org/wiki/Graphical_user_interface 77 | [destructuring-assignment]: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment -------------------------------------------------------------------------------- /api/touch-bar-button.md: -------------------------------------------------------------------------------- 1 | ## 类:TouchBarButton 2 | 3 | >在本地MacOS应用程序的触摸栏中创建一个按钮 4 | 5 | 进程: [主进程](../tutorial/quick-start.md#主进程) 6 | 7 | ### `new TouchBarButton(options)` _实验功能_ 8 | >用途:**创建新按钮** 9 | 10 | * `options` Object 11 | * `label` String (可选) - 按钮文本 12 | * `backgroundColor` String (可选) - 十六进制的按钮背景颜色如 `#ABCDEF` 13 | * `icon` [NativeImage](native-image.md) (可选) - 按钮图标 14 | * `iconPosition` String - 可选 `left`, `right` 或 `overlay`. 15 | * `click` Function (可选) - 单击按钮时调用 16 | 17 | ### 实例属性 18 | 19 | `TouchBarButton`实例有以下属性: 20 | 21 | #### `touchBarButton.label` 22 | >属性:**按钮的当前文本** 23 | 24 | #### `touchBarButton.backgroundColor` 25 | >属性:**按钮的当前背景颜色** 26 | 27 | #### `touchBarButton.icon` 28 | >属性:**按钮的当前图标** -------------------------------------------------------------------------------- /api/touch-bar-color-picker.md: -------------------------------------------------------------------------------- 1 | ## 类: TouchBarColorPicker 2 | 3 | >在本地MacOS应用程序的触摸条中创建颜色选择器 4 | 5 | 进程: [主进程](../tutorial/quick-start.md#主进程) 6 | 7 | ### `new TouchBarColorPicker(options)` _实验功能_ 8 | >用途:**创建颜色选择器** 9 | 10 | * `options` Object 11 | * `availableColors` String[] (可选) - 十六进制格式的可选颜色组成的字符串数组 12 | * `selectedColor` String (可选) - 选中项的十六进制格式颜色 如`#ABCDEF`. 13 | * `change` Function (可选) - 选择颜色时调用 14 | 15 | ### 实例属性 16 | `TouchBarColorPicker`有以下属性: 17 | 18 | #### `touchBarColorPicker.availableColors` 19 | >属性:**颜色选择器的可选颜色** 20 | 21 | #### `touchBarColorPicker.selectedColor` 22 | >属性:**颜色选择器当前选择的颜色** -------------------------------------------------------------------------------- /api/touch-bar-group.md: -------------------------------------------------------------------------------- 1 | ## 类: TouchBarGroup 2 | >在触摸栏中为本机macOS应用程序创建一个分组 3 | 4 | 进程: [主进程](../tutorial/quick-start.md#主进程) 5 | 6 | ### `new TouchBarGroup(options)` _实验功能_ 7 | >用途:**创建一个新的分组** 8 | 9 | * `options` Object 10 | * `items` [TouchBar](touch-bar.md) - 作为一个组显示的项目 -------------------------------------------------------------------------------- /api/touch-bar-label.md: -------------------------------------------------------------------------------- 1 | ## 类: TouchBarLabel 2 | >在触摸条中为本机macOS应用程序创建一个label标签 3 | 4 | 进程: [主进程](../tutorial/quick-start.md#main-process) 5 | 6 | ### `new TouchBarLabel(options)` _实验功能_ 7 | >用途:**创建一个新的label标签** 8 | 9 | * `options` Object 10 | * `label` String (可选) - 要显示的文本 11 | * `textColor` String (可选) - 十六进制的文本颜色, 如`#ABCDEF`. 12 | 13 | 14 | ### 实例属性 15 | `TouchBarLabel`有以下属性: 16 | 17 | #### `touchBarLabel.label` 18 | >属性:**label标签的当前文本** 19 | 20 | #### `touchBarLabel.textColor` 21 | >属性:**label标签的当前文本颜色** -------------------------------------------------------------------------------- /api/touch-bar-popover.md: -------------------------------------------------------------------------------- 1 | ## 类: TouchBarPopover 2 | 3 | > 在本地MacOS应用程序的触摸栏中创建一个Popover弹出框 4 | 5 | 进程: [主进程](../tutorial/quick-start.md#主进程) 6 | 7 | ### `new TouchBarPopover(options)` _实验功能_ 8 | >用途:**创建新Popover弹出框** 9 | 10 | * `options` Object 11 | * `label` String (可选) - Popover按钮文本 12 | * `icon` [NativeImage](native-image.md) (可选) - Popover按钮图标 13 | * `items` [TouchBar](touch-bar.md) (可选) - 在Popover弹出框中显示的项目 14 | * `showCloseButton` Boolean (可选) - 是否在左侧显示关闭文本,默认为 `false`. 15 | 16 | ### 实例属性 17 | `TouchBarPopover`有以下属性: 18 | 19 | #### `touchBarPopover.label` 20 | >属性:**Popover的当前按钮文本** 21 | 22 | #### `touchBarPopover.icon` 23 | >属性:**Popover的当前按钮图标** 24 | -------------------------------------------------------------------------------- /api/touch-bar-scrubber.md: -------------------------------------------------------------------------------- 1 | ## 类: TouchBarScrubber 2 | 3 | >创建一个scrubber(一个可滚动的选择器) 4 | 5 | 进程: [主进程](../tutorial/quick-start.md#主进程) 6 | 7 | ### `new TouchBarScrubber(options)` _实验功能_ 8 | > 用途: ** 创建一个新的scrubber** 9 | 10 | * `options` Object 11 | * `items` [ScrubberItem[]](structures/scrubber-item.md) - 要放置在此scrubber中的项数组 12 | * `select` Function - 当用户点击的不是最后一个点击项时调用 13 | * `selectedIndex` Integer - 用户选择项的索引 14 | * `highlight` Function - 当用户点击任何项时调用 15 | * `highlightedIndex` Integer - 用户触摸项的索引 16 | * `selectedStyle` String - 所选项样式。默认为 `null`. 17 | * `overlayStyle` String - 选择的覆盖项样式 默认为 `null`. 18 | * `showArrowButtons` Boolean - 默认为 `false`. 19 | * `mode` String - 默认为 `free`. 20 | * `continuous` Boolean - 默认为 `true`. 21 | 22 | ### 实例属性 23 | `TouchBarScrubber`有以下实例属性: 24 | 25 | #### `touchBarSegmentedControl.items` 26 | > 属性: ** scrubber中的项组成的数组( `ScrubberItem[]`)** 27 | 28 | #### `touchBarSegmentedControl.selectedStyle` 29 | > 属性: ** scrubber中的选择项的样式( `String`)** 30 | 31 | 可能的值: 32 | * `background` - 映射到 `[NSScrubberSelectionStyle roundedBackgroundStyle]` 33 | * `outline` - 映射到 `[NSScrubberSelectionStyle outlineOverlayStyle]` 34 | * `null` - null时表示删除所有样式. 35 | 36 | #### `touchBarSegmentedControl.overlayStyle` 37 | > 属性: ** scrubber中的选择项的覆盖样式( `String`)** 38 | 39 | 可能的值: 40 | `background` - 映射到 `[NSScrubberSelectionStyle roundedBackgroundStyle]` 41 | * `outline` - 映射到 `[NSScrubberSelectionStyle outlineOverlayStyle]` 42 | * `null` - null时表示删除所有样式. 43 | 44 | #### `touchBarSegmentedControl.showArrowButtons` 45 | > 属性: ** 是否在scrubber中显示左右提示箭头( `Boolean`)** 46 | 47 | #### `touchBarSegmentedControl.mode` 48 | > 属性: ** scrubber的模式( `String`)** 49 | 50 | * `fixed` - 映射到 `NSScrubberModeFixed` 51 | * `free` - 映射到 `NSScrubberModeFree` 52 | 53 | #### `touchBarSegmentedControl.continuous` 54 | > 属性: ** scrubber是否是连续的( `Boolean`)** -------------------------------------------------------------------------------- /api/touch-bar-segmented-control.md: -------------------------------------------------------------------------------- 1 | ## 类: TouchBarSegmentedControl 2 | 3 | > 选中按钮时创建一个分段控件(按钮组) 4 | 5 | 进程: [主进程](../tutorial/quick-start.md#主进程) 6 | 7 | ### `new TouchBarSegmentedControl(options)` _实验功能_ 8 | > 用途:**当用户选中按钮时创建一个新的分段控件并调用 `change`** 9 | 10 | * `options` Object 11 | * `segmentStyle` String -可选的分段样式: 12 | * `automatic` - 默认值. 按显示控件的窗口类型与窗口内的位置进行自动选择分段控件的合适外观. 13 | * `rounded` - 使用圆形样式显示控件 14 | * `round-rect` - 使用圆弧形显示控件 15 | * `textured-rounded` - 使用纹理圆形样式显示控件 16 | * `textured-square` - 使用纹理方形样式显示控件 17 | * `capsule` - 使用胶囊形样式显示控件 18 | * `small-square` - 使用小方形样式显示控件 19 | * `separated` - 使用段之间紧密相连又不相互接触的样式显示控件 20 | * `mode` String - (可选) 可选模式如下: 21 | * `single` - 默认. 单次选择一个,选择新项时将取消上一次的选择 22 | * `multiple` - 单次可选多项 23 | * `buttons` - 使段作为按钮,段可以按下并释放但从未标记为活动 24 | * `segments` [SegmentedControlSegment[]](structures/segmented-control-segment.md) - 要放置在此控件中的段数组 25 | * `selectedIndex` Integer (可选) - 当前所选段的索引,将通过用户交互自动更新.当多个模式时默认选定最后一个. 26 | * `change` Function - 当用户选择一个新段时调用 27 | * `selectedIndex` Integer - 用户所选段的索引 28 | * `isSelected` Boolean - 用户选择结果 29 | 30 | ### 实例属性 31 | 32 | `TouchBarSegmentedControl`有以下实例属性: 33 | 34 | #### `touchBarSegmentedControl.segmentStyle` 35 | > 属性: ** 控件当前段的样式( `String`)** 36 | 37 | #### `touchBarSegmentedControl.segments` 38 | > 属性: ** 此控件中的段组成的数组( `SegmentedControlSegment[]`)** 39 | 40 | 注意,当仅更新数组中的深层次属性时,触摸条不会即时更新. 41 | 42 | #### `touchBarSegmentedControl.selectedIndex` 43 | > 属性: ** 当前选定的段( `Integer`)** 44 | 45 | -------------------------------------------------------------------------------- /api/touch-bar-slider.md: -------------------------------------------------------------------------------- 1 | ## 类: TouchBarSlider 2 | 3 | >在本地MacOS应用程序的触摸栏中创建滑块 4 | 5 | 进程: [主进程](../tutorial/quick-start.md#主进程) 6 | 7 | ### `new TouchBarSlider(options)` _实验功能_ 8 | >用途:**创建新滑块** 9 | 10 | * `options` Object 11 | * `label` String (可选) - 标签文本. 12 | * `value` Integer (可选) - 所选值 13 | * `minValue` Integer (可选) - 最小值 14 | * `maxValue` Integer (可选) - 最大值 15 | * `change` Function (可选) - 滑块改变时调用的函数 16 | 17 | ### 实例属性 18 | 19 | `TouchBarSlider`有以下属性: 20 | 21 | #### `touchBarSlider.label` 22 | >属性:**滑块的当前文本** 23 | 24 | #### `touchBarSlider.value` 25 | >属性:**滑块的当前值** 26 | 27 | #### `touchBarSlider.minValue` 28 | >属性:**滑块的当前最小值** 29 | 30 | #### `touchBarSlider.maxValue` 31 | >属性:**滑块的当前最大值** -------------------------------------------------------------------------------- /api/touch-bar-spacer.md: -------------------------------------------------------------------------------- 1 | ## 类: TouchBarSpacer 2 | 3 | > 在本地MacOS应用程序的触摸条中的两个项目之间创建一个间隔 4 | 5 | 进程: [主进程](../tutorial/quick-start.md#主进程) 6 | 7 | ### `new TouchBarSlider(options)` _实验功能_ 8 | >用途:**创建新间隔** 9 | 10 | * `options` Object 11 | * `size` String (可选) - 间隔大小,可选值有: 12 | * `small` - 小间隔 13 | * `large` - 大间隔 14 | * `flexible` - 占用所有可用空间 -------------------------------------------------------------------------------- /api/touch-bar.md: -------------------------------------------------------------------------------- 1 | # 类:TouchBar触摸条 2 | 3 | >为本机macOS应用程序创建TouchBar布局 4 | 5 | 进程: [主进程](../tutorial/quick-start.md#主进程) 6 | 7 | ## `new TouchBar(options)` _实验功能_ 8 | >用途:**使用指定项目创建新的触摸条,使用 `BrowserWindow.setTouchBar`将 `TouchBar`加到窗口中** 9 | 10 | * `options` - Object 11 | * `items` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md))[] 12 | * `escapeItem` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarScrubber](touch-bar-scrubber.md) | [TouchBarSegmentedControl](touch-bar-segmented-control.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md)) (可选) 13 | 14 | 15 | **提醒:** 如果您没有自带触控板的MacBook的话,可以使用这个[触控板模拟器](https://github.com/sindresorhus/touch-bar-simulator). 16 | 17 | **注意:** TouchBar API 目前是实验功能,未来可能删除. 18 | 19 | 下面是个用在摇一摇或老虎机,贩卖机上的简单的带有按钮的触摸条例子: 20 | 21 | ```javascript 22 | const {app, BrowserWindow, TouchBar} = require('electron') 23 | 24 | const {TouchBarLabel, TouchBarButton, TouchBarSpacer} = TouchBar 25 | 26 | let spinning = false 27 | 28 | //卷轴标签 29 | const reel1 = new TouchBarLabel() 30 | const reel2 = new TouchBarLabel() 31 | const reel3 = new TouchBarLabel() 32 | 33 | //旋转结果标签 34 | const result = new TouchBarLabel() 35 | 36 | //旋转按钮 37 | const spin = new TouchBarButton({ 38 | label: '🎰 Spin', 39 | backgroundColor: '#7851A9', 40 | click: () => { 41 |    //忽略已经旋转的点击 42 | if (spinning) { 43 | return 44 | } 45 | 46 | spinning = true 47 | result.label = '' 48 | 49 | let timeout = 10 50 | const spinLength = 4 * 1000 // 4 seconds 51 | const startTime = Date.now() 52 | 53 | const spinReels = () => { 54 | updateReels() 55 | 56 | if ((Date.now() - startTime) >= spinLength) { 57 | finishSpin() 58 | } else { 59 |   //每次旋转减慢一点 60 | timeout *= 1.1 61 | setTimeout(spinReels, timeout) 62 | } 63 | } 64 | 65 | spinReels() 66 | } 67 | }) 68 | 69 | const getRandomValue = () => { 70 | const values = ['🍒', '💎', '7️⃣', '🍊', '🔔', '⭐', '🍇', '🍀'] 71 | return values[Math.floor(Math.random() * values.length)] 72 | } 73 | 74 | const updateReels = () => { 75 | reel1.label = getRandomValue() 76 | reel2.label = getRandomValue() 77 | reel3.label = getRandomValue() 78 | } 79 | 80 | const finishSpin = () => { 81 | const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size 82 | if (uniqueValues === 1) { 83 |  //3个相同值 84 | result.label = '💰 Jackpot!' 85 | result.textColor = '#FDFF00' 86 | } else if (uniqueValues === 2) { 87 |     // 2个相同值 88 | result.label = '😍 Winner!' 89 | result.textColor = '#FDFF00' 90 | } else { 91 |   //没有相同值 92 | result.label = '🙁 Spin Again' 93 | result.textColor = null 94 | } 95 | spinning = false 96 | } 97 | 98 | const touchBar = new TouchBar([ 99 | spin, 100 | new TouchBarSpacer({size: 'large'}), 101 | reel1, 102 | new TouchBarSpacer({size: 'small'}), 103 | reel2, 104 | new TouchBarSpacer({size: 'small'}), 105 | reel3, 106 | new TouchBarSpacer({size: 'large'}), 107 | result 108 | ]) 109 | 110 | let window 111 | 112 | app.once('ready', () => { 113 | window = new BrowserWindow({ 114 | frame: false, 115 | titleBarStyle: 'hidden-inset', 116 | width: 200, 117 | height: 200, 118 | backgroundColor: '#000' 119 | }) 120 | window.loadURL('about:blank') 121 | window.setTouchBar(touchBar) 122 | }) 123 | ``` 124 | 125 | ### 上方代码的运行方法 126 | 127 | 假设已有终端已打开您期望的例子并打算运行上方的例子,那么你需要这么做: 128 | 129 | 1. 将上面的内容以 `touchbar.js`文件保存到计算机中. 130 | 2. 如果没有安装electron的话,则通过npm安装electron 如 `npm install electron`. 131 | 3. 在Electron中运行: `./node_modules/.bin/electron touchbar.js` 132 | 133 | 这样,您就能看到一个新窗口,而触摸条中也将运行相应程序. 134 | 135 | -------------------------------------------------------------------------------- /api/web-frame.md: -------------------------------------------------------------------------------- 1 | # 模块:webFrame(自定义渲染页面) 2 | 3 | > `web-frame` 模块可自定义渲染当前网页 4 | 5 | 进程: [渲染进程](../glossary.md#渲染进程) 6 | 7 | 例如放大当前页至 200%. 8 | 9 | ```JavaScript 10 | const {webFrame} = require('electron') 11 | webFrame.setZoomFactor(2) 12 | ``` 13 | 14 | ## 方法 15 | 16 | ### `webFrame.setZoomFactor(factor)` 17 | > 用途:**设置页面的缩放系数** 18 | 19 | * `factor` Number - 缩放系数 20 | 21 | 注意:缩放系数是百分制的,如3.0=300%。 22 | 23 | ### `webFrame.getZoomFactor()` 24 | > 用途:**获得当前缩放系数( `Number`)** 25 | 26 | ### `webFrame.setZoomLevel(level)` 27 | > 用途:**将缩放级别更改为指定级别** 28 | 29 | * `level` Number - 缩放级别 30 | 31 | 原始大小为0,每个增量表示放大或缩小20%,默认限制为原始大小的300%至50%。 32 | 33 | ### `webFrame.getZoomLevel()` 34 | > 用途:**获得当前缩放级别( `Number`)** 35 | 36 | ### `webFrame.setVisualZoomLevelLimits(minimumLevel, maximumLevel)` 37 | > 用途:**设置缩放级别的最大值和最小值** 38 | 39 | * `minimumLevel` Number 40 | * `maximumLevel` Number 41 | 42 | ### `webFrame.setLayoutZoomLevelLimits(minimumLevel, maximumLevel)` 43 | > 用途:**设置基于布局(即非视觉)的缩放级别的最大值和最小值** 44 | 45 | * `minimumLevel` Number 46 | * `maximumLevel` Number 47 | 48 | ### `webFrame.setSpellCheckProvider(language, autoCorrectWord, provider)` 49 | > 用途:**为输入框或文本域设置拼写检查的提供程序** 50 | 51 | * `language` String 52 | * `autoCorrectWord` Boolean 53 | * `provider` Object 54 | * `spellCheck` Function - 返回 `Boolean` 55 | * `text` String 56 | 57 | `provider`必须是具有 `spellCheck`方法的对象,该方法返回扫过的单词是否拼写正确。 58 | 59 | 把[node-spellchecker][spellchecker]作为提供程序的示例: 60 | 61 | ```JavaScript 62 | const {webFrame} = require('electron') 63 | webFrame.setSpellCheckProvider('en-US', true, { 64 | spellCheck (text) { 65 | return !(require('spellchecker').isMisspelled(text)) 66 | } 67 | }) 68 | ``` 69 | 70 | ### `webFrame.registerURLSchemeAsSecure(scheme)` 71 | > 用途:**将 `scheme` 注册为安全协议** 72 | 73 | * `scheme` String 74 | 75 | 例如, `https`和 `data`是安全的协议,它不能轻易的被黑客破坏。 76 | 77 | ### `webFrame.registerURLSchemeAsBypassingCSP(scheme)` 78 | > 用途:**忽略当前页面的内容安全策略,资源全部从此 `scheme` 加载** 79 | 80 | * `scheme` String 81 | 82 | ### `webFrame.registerURLSchemeAsPrivileged(scheme[, options])` 83 | > 用途:**忽略内容安全策略,将 `scheme` 注册为安全协议且允许注册ServiceWorker和支持fetch API** 84 | 85 | * `scheme` String 86 | * `options` Object (可选) 87 | * `secure` Boolean - (可选) 默认为 `true` 88 | * `bypassCSP` Boolean - (可选) 默认为 `true` 89 | * `allowServiceWorkers` Boolean - (可选) 默认为 `true` 90 | * `supportFetchAPI` Boolean - (可选) 默认为 `true` 91 | * `corsEnabled` Boolean - (可选) 默认为 `true` 92 | 93 | 以上选项值如指定 `false`则表示从注册中忽视该选项。 94 | 95 | 在不绕过内容安全策略的情况下注册特权方案的示例: 96 | ```JavaScript 97 | const {webFrame} = require('electron') 98 | webFrame.registerURLSchemeAsPrivileged('foo', { bypassCSP: false }) 99 | ``` 100 | 101 | ### `webFrame.insertText(text)` 102 | > 用途:**插入 `text` 到焦点元素** 103 | 104 | * `text` String 105 | 106 | ### `webFrame.executeJavaScript(code[, userGesture, callback])` 107 | > 用途:**在页面中评估(eval) `code`( `Promise`)** 108 | 109 | * `code` String 110 | * `userGesture` Boolean (可选) - 默认为 `false`,设置为 `true`时可使某些HTML API(如 `requestFullScreen`)手势去除由用户手势进行调用的限制 。 111 | * `callback` Function (可选) - 在脚本执行后调用 112 | * `result` Any 113 | 114 | 115 | 返回 `Promise` - 如果被正确执行则返回可用的承诺,否则将被拒绝。 116 | 117 | 在浏览器窗口中,一些HTML API(如`requestFullScreen`)只能由用户的手势调用。 需要将 `userGesture`设置为 `true`进行消除这个限制。 118 | 119 | ### `webFrame.getResourceUsage()` 120 | > 用途:**获取描述Blink内存缓存信息的对象( `Object`)** 121 | 122 | * `images` [MemoryUsageDetails](structures/memory-usage-details.md) 123 | * `cssStyleSheets` [MemoryUsageDetails](structures/memory-usage-details.md) 124 | * `xslStyleSheets` [MemoryUsageDetails](structures/memory-usage-details.md) 125 | * `fonts` [MemoryUsageDetails](structures/memory-usage-details.md) 126 | * `other` [MemoryUsageDetails](structures/memory-usage-details.md) 127 | 128 | ```JavaScript 129 | const {webFrame} = require('electron') 130 | console.log(webFrame.getResourceUsage()) 131 | ``` 132 | 133 | 这将生成: 134 | ```JavaScript 135 | { 136 | images: { 137 | count: 22, 138 | size: 2549, 139 | liveSize: 2542, 140 | }, 141 | cssStyleSheets: { /* 类同上行的 `images` */ }, 142 | xslStyleSheets: { /* 类同上行的 `images` */ }, 143 | fonts: { /* 类同上行的 `images` */ }, 144 | other: { /* 类同上行的 `images` */ } 145 | } 146 | ``` 147 | 148 | ### `webFrame.clearCache()` 149 | > 用途:**释放无用内存(如如来自上一个导航的图像)** 150 | 151 | 如果盲调用此方法,可能会使Electron运行比较卡,因为它将不得不重新填充这些空的缓存! 152 | 153 | 建议在某些比较消耗内存的应用事件时才进行调用,比如加载了个很冗长复杂且需长时间停留使用的页面. 154 | 155 | [spellchecker]: https://github.com/atom/node-spellchecker -------------------------------------------------------------------------------- /api/window-open.md: -------------------------------------------------------------------------------- 1 | # 本文介绍:`window.open` 2 | 3 | > 用于打开url或载入url至 `BrowserWindow` ,并对该窗口进行少量功能的控制. 4 | 5 | 使用 `window.open` 创建一个新窗口时,会自动创建一个 `BrowserWindowProxy` 的实例将返回一个标识,可通过标识对这个新窗口进行少量功能的控制. 6 | 7 | 不过希望完全的控制这个窗口,请直接创建一个 `BrowserWindow` .新创建的 `BrowserWindow` 默认为继承父窗口的属性参数,想重写属性的话可以在 `features` 中设置它们. 8 | 9 | ### `window.open(url[, frameName][, features])` 10 | >用途:**新窗口并返回一个`BrowserWindowProxy`类的实例([`BrowserWindowProxy`](browser-window-proxy.md))** 11 | 12 | * `url` String 13 | * `frameName` String (可选) 14 | * `features` String (可选) - 字符串遵循标准浏览器的格式,但是每个 `feature`必须是一个 `BrowserWindow`选项的字段。 15 | 16 | **Notes:** 17 | 18 | * 父窗口中禁用Node时,open的新开窗口中也始终禁用Node。 19 | * 父窗口中禁用JavaScript时,open的新开窗口中也始终禁用JavaScript。 20 | * 父窗口中启动上下文隔离时,open的新开窗口中也始终启动上下文隔离。 21 | 22 | `features` 中指定的不由Chromium或Electron处理的非标准特性将传递给 `additionalFeatures`参数中的任何已注册的 `webContent` 的 `new-window`新窗口事件处理程序。 23 | 24 | ### `window.opener.postMessage(message, targetOrigin)` 25 | >用途:**向指定位置或用 `*` 来代替没有明确位置来向父窗口发送消息** 26 | 27 | * `message` String 28 | * `targetOrigin` String -------------------------------------------------------------------------------- /demo/README.md: -------------------------------------------------------------------------------- 1 | ## 前言: 2 | 本目录为本人app的创作杂记,目标为创建具有与jquery,php完全融合一体的电商管理平台. 3 | 4 | ## 应用流程: 5 | 6 | ### 初始载入:托盘图标_Tray_ 7 | 8 | * 1. 系统托盘 - `.json` 9 | * 1.1 图标 - 离线图标(图标统一格式: `png`,个人状态:正常,忙碌,离开,离线,信息状态:新消息闪烁) 10 | * 1.2 单击显示主窗口 11 | * 1.3 右击菜单 12 | * 1.3.1 灰色待登录头像 13 | * 1.3.2 帮助 - 弹出工单提交窗 14 | * 1.3.3 反馈 - 弹出反馈提交窗 15 | * 1.3.4 退出 - 关闭应用 16 | 17 | 图示: 18 | 19 | ![image](images/03.png) 20 | 21 | > API: [系统托盘](/api/tray.md) 22 | 23 | ### 初始载入:载入动图_Loading_ 24 | 25 | * 2. 动图Loading窗 - `.json` 26 | * 2.1 服务更新 - 服务器端进行维护或暂停时弹出提示并冻结应用. 27 | * 2.2 设备与性能 - 屏幕,系统,语言等,载入适合的大小与界面语言. 28 | * 2.3 版本更新 - 新版本时进行更新并重载本窗. 29 | * 2.4 安全扫描 - 无任何登录记录的本异地使用(如新装,异地下载后安装,弹出主管手机确认码 30 | * 2.5 动图滑动为登录窗 31 | 32 | 图示: 33 | 34 | ![image](images/01.png) 35 | 36 | ![image](images/02.gif) 37 | 38 | ### 初始载入:监听 39 | 40 | * 0. 全程监听 - `online-offline` 41 | * 实时联网 - 断网即显示线下状态 42 | > API: [在线/离线事件检测](/tutorial/online-offline-events.md) 43 | 44 | ### 初始载入:登录窗 45 | 46 | * 3. 登录窗 - `.json` 47 | * 3.1 窗口菜单 48 | * 3.1.1 小菜单 49 | * 3.1.1.1 注册账号 50 | * 3.1.1.2 找回密码 51 | * 3.1.1.2 使用条款 52 | * 3.1.1.2 关于应用 53 | * 3.1.1.2 退出 54 | * 3.1.2 最小化 55 | * 3.1.2 退出 56 | * 3.2 头像 57 | * 3.3 账号输入框 - 邮箱/手机号/工号 58 | * 3.4 密码输入框 - 密码 59 | * 3.5 记住密码/自动登录 60 | * 3.6 现在登录 61 | * 3.7 APP/微信二维码 - 翻转显示可识别二维码. 62 | 63 | 图示: 64 | 65 | ![image](images/05.png) 66 | 67 | ### 已登录后的业务载入:托盘变化 68 | 69 | * 1. 系统托盘 - `.json` 70 | * 1.1 图标 - 在线图标 71 | * 1.2 单击显示窗口 72 | * 1.3 右击菜单 73 | * 1.3.1 个人头像,单位,职位 74 | * 1.3.2 个人功能区 - 根据用户自定义选择的5个以内的对应快捷菜单,以下以店长为例 75 | * 1.3.1 店铺管理 76 | * 1.3.1 店铺设置 77 | * 1.3.1 我要发货 78 | * 1.3.3 隐藏悬浮窗 79 | * 1.3.4 帮助 - 弹出工单提交窗 80 | * 1.3.5 反馈 - 弹出反馈提交窗 81 | * 1.3.6 注销 - 销毁用户缓存 82 | * 1.3.7 退出 - 关闭应用 83 | 84 | 图示: 85 | 86 | ![image](images/04.png) 87 | 88 | ### 已登录后的业务载入:悬浮窗 89 | 90 | * 2. 悬浮窗 - `.json` -展示消息,通知(如下单,下级店员权限申请)或快速菜单等,提高应用的便捷性 91 | * 2.1 单击 - 消息/任务/提醒小窗 92 | * 2.2 右击 - 快速菜单栏 93 | * 2.2.1 自定义的快速菜单栏 94 | * 2.2.2 显示主界面 95 | * 2.2.3 显示悬浮窗 96 | * 2.2.4 退出 97 | 98 | 图示: 99 | 100 | ![image](images/06.png) 101 | 102 | ![image](images/07.png) 103 | 104 | ### 已登录后的业务载入:主平台 105 | 106 | * 3. 主平台 - `.json` - 综合性处理的主窗口(多身份通用型) 107 | * 3.1 窗口菜单 108 | * 3.1.0 主题设置 - 弹出可选主题. 109 | * 3.1.1 小菜单 110 | * 3.1.1.1 系统设置 111 | * 3.1.1.2 检查更新 112 | * 3.1.1.2 切换账号 113 | * 3.1.1.2 关于应用 114 | * 3.1.1.2 退出 115 | * 3.1.2 全屏 116 | * 3.1.3 最小化 117 | * 3.1.4 最大化 118 | * 3.1.5 关闭 119 | * 3.2 系统公告区 120 | * 3.2.1 系统公告 121 | * 3.2.2 在线人数统计(前后台) 122 | * 3.3 系统功能区 123 | * 3.3.1 前进 124 | * 3.3.2 后退 125 | * 3.3.3 搜索栏 126 | * 3.3.2 快速直达区 127 | * 3.4 用户资料区 128 | * 3.4.1 头像 129 | * 3.4.2 用户名 130 | * 3.4.3 所在店铺 131 | * 3.4.4 当前职位 132 | * 3.4.5 编辑资料 133 | * 3.4.6 消息盒子 134 | * 3.4.7 个人记录 135 | * 3.5 系统业务区 136 | * 3.5.1 主页 137 | * 3.5.2 应用中心 138 | * 3.5.3 商店 139 | * 3.5.4 个人功能区 140 | * 3.5.5 内部交流区 141 | * 3.6 系统内容区域- 自适应模块式布局 -------------------------------------------------------------------------------- /demo/images/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/01.png -------------------------------------------------------------------------------- /demo/images/02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/02.gif -------------------------------------------------------------------------------- /demo/images/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/03.png -------------------------------------------------------------------------------- /demo/images/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/04.png -------------------------------------------------------------------------------- /demo/images/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/05.png -------------------------------------------------------------------------------- /demo/images/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/06.png -------------------------------------------------------------------------------- /demo/images/07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/07.png -------------------------------------------------------------------------------- /demo/images/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/08.png -------------------------------------------------------------------------------- /demo/images/09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/09.png -------------------------------------------------------------------------------- /demo/images/10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/10.gif -------------------------------------------------------------------------------- /demo/images/now.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/now.png -------------------------------------------------------------------------------- /demo/images/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/qq.png -------------------------------------------------------------------------------- /demo/images/trayWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amhoho/electron-cn-docs/167c755e19f942593f8ed0aa17964bd78f0092b2/demo/images/trayWindow.png -------------------------------------------------------------------------------- /development/README.md: -------------------------------------------------------------------------------- 1 | # 开发指南目录: 2 | * [构建说明(Linux)](build-instructions-linux.md) 3 | * [构建说明(macOS)](build-instructions-osx.md) 4 | * [构建说明(Windows)](build-instructions-windows.md) 5 | * [构建系统概述](build-system-overview.md) 6 | * [编码规范](coding-style.md) 7 | * [在 macOS 中调试](debugging-instructions-macos.md) 8 | * [在 Windows 中调试](debug-instructions-windows.md) 9 | * [在C ++代码中使用clang-format](clang-format.md) 10 | * [在调试器中设置符号服务器](setting-up-symbol-server.md) 11 | * [源代码目录结构](source-code-directory-structure.md) 12 | * [Chrome升级清单](upgrading-chrome.md) 13 | * [Chromium 开发指南](chromium-development.md) 14 | * [V8 开发指南](v8-development.md) -------------------------------------------------------------------------------- /development/build-instructions-linux.md: -------------------------------------------------------------------------------- 1 | # 构建说明(Linux) 2 | 3 | > 在Linux中,构建Electron 4 | 5 | ## 前提要求 6 | 7 | * 磁盘可用空间>=25GB 8 | * 内存>=8GB 9 | * Python>=2.7.x以上版本,比如 CentOS 6.x 是基于Python 2.6.x.你可以使用 `python -V`命令自查版本. 10 | * Node.js. 你可以在[Node.js](http://nodejs.org)或者[NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories)下载Node.js. 11 | * Clang>=3.4以上版本 12 | * GTK+开发头文件和libnotify. 13 | 14 | > Ubuntu:**安装以下库** 15 | 16 | ```bash 17 | $ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \ 18 | libnotify-dev libgnome-keyring-dev libgconf2-dev \ 19 | libasound2-dev libcap-dev libcups2-dev libxtst-dev \ 20 | libxss1 libnss3-dev gcc-multilib g++-multilib curl \ 21 | gperf bison 22 | ``` 23 | 24 | > RHEL/CentOS:**安装以下库** 25 | 26 | ```bash 27 | $ sudo yum install clang dbus-devel gtk2-devel libnotify-devel \ 28 | libgnome-keyring-devel xorg-x11-server-utils libcap-devel \ 29 | cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \ 30 | GConf2-devel nss-devel 31 | ``` 32 | 33 | > Fedora:**安装以下库** 34 | 35 | ```bash 36 | $ sudo dnf install clang dbus-devel gtk2-devel libnotify-devel \ 37 | libgnome-keyring-devel xorg-x11-server-utils libcap-devel \ 38 | cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \ 39 | GConf2-devel nss-devel 40 | ``` 41 | 42 | 其他发行版可利用pacman之类的软件包管理器安装,也或者可以从源代码编译. 43 | 44 | ## 获取代码 45 | ```bash 46 | $ git clone https://github.com/electron/electron.git 47 | ``` 48 | 49 | ## 引导 50 | 51 | 引导脚本将下载所有必需的构建依赖项并创建构建项目文件,某些文件可能需要花费很长的时间. 52 | 53 | 注意,必须有Python 2.7.x才能成功,由于使用了 `ninja`进行构建,因此不存在 `Makefile`项目. 54 | 55 | ```bash 56 | $ cd electron 57 | $ ./script/bootstrap.py -v 58 | ``` 59 | 60 | ### 交叉编译 61 | 62 | 如果你想要构建一个 `arm` target,你还应该安装以下依赖: 63 | ```bash 64 | $ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \ 65 | g++-arm-linux-gnueabihf 66 | ``` 67 | 68 | 要交叉编译 `arm`或 `ia32` target,你应该将 `--target_arch`参数传递给 `bootstrap.py`脚本: 69 | ```bash 70 | $ ./script/bootstrap.py -v --target_arch=arm 71 | ``` 72 | 73 | ## 构建 74 | 75 | 创建 `Release`和 `Debug` target: 76 | ```bash 77 | $ ./script/build.py 78 | ``` 79 | 80 | 这个脚本将在 `out/R`目录下生成一个大小超过1.3GB的Electron可执行文件. 81 | 82 | 之所以这么大,是因为Release target包含了调试符号.运行 `create-dist.py`脚本可减小文件大小: 83 | 84 | ```bash 85 | $ ./script/create-dist.py 86 | ``` 87 | 88 | 这将在 `dist`目录里创建一个大量小文件的工作分配.运行create-dist.py脚本后,或许你想删除仍然在 `out/R`中的那个超过1.3GB的文件. 89 | 90 | 还可以仅构建 `Debug` target : 91 | 92 | ```bash 93 | $ ./script/build.py -c D 94 | ``` 95 | 96 | 在构建完成后,你可以在 `out/D`下找到 `electron` debug二进制文件. 97 | 98 | ## 清理 99 | 100 | 清理构建文件: 101 | ```bash 102 | $ npm run clean 103 | ``` 104 | 105 | 只清理`out`和`dist`目录: 106 | 107 | ```bash 108 | $ npm run clean-build 109 | ``` 110 | 111 | **注意:**以上两个clean命令都需要在构建之前再次运行 `bootstrap`。 112 | 113 | ## 故障排除 114 | 115 | ### 加载共享库时出错:libtinfo.so.5 116 | 117 | 预构建的 `clang`会尝试链接到 `libtinfo.so.5`,并根据主机体系结构进行链接到适当的 `libncurses`: 118 | ```bash 119 | $ sudo ln -s /usr/lib/libncurses.so.5 /usr/lib/libtinfo.so.5 120 | ``` 121 | 122 | ## 相关测试 123 | 124 | 参见[构建系统概述:测试](build-system-overview.md#tests) 125 | 126 | ## 延伸问题 127 | 128 | 默认的构建配置是针对主流的Linux桌面发行版,至于特定发行版或设备进行构建,你可以了解以下信息: 129 | 130 | ### 本地构建 `libchromiumcontent` 131 | 132 | 为了避免使用 `libchromiumcontent`的预编译二进制文件,你可以将 `--build_libchromiumcontent`切换到 `bootstrap.py`脚本: 133 | ```bash 134 | $ ./script/bootstrap.py -v --build_libchromiumcontent 135 | ``` 136 | 137 | 默认情况下不会以 `shared_library` 方式进行构建, 所以你如果使用以下模式的话, 只能构建 Electron的 `Release` 版本: 138 | ```bash 139 | $ ./script/build.py -c R 140 | ``` 141 | 142 | ### 使用系统`clang` 143 | 144 | 默认情况下 Electron 使用 Chromium 项目提供的预编译的 `clang` 进行编译. 145 | 146 | 如果基于某些原因,你想要使用已经安装到系统的 `clang` 进行编译, 可以添加 `--clang_dir=` 参数给 `bootstrap.py` 以指定 `clang` 安装路径. 147 | 148 | 上面参数告诉编译脚本, 在目录 `/bin/` 下有 `clang` 程序. 149 | 150 | 假设你的 `clang` 安装路径为 `/user/local/bin/clang`: 151 | ```bash 152 | $ ./script/bootstrap.py -v --build_libchromiumcontent --clang_dir /usr/local 153 | $ ./script/build.py -c R 154 | ``` 155 | 156 | ### 使用 `clang` 之外的其它编译器 157 | 158 | 要使用 `g++`这样的编译器来构建Electron,先使用 `--disable_clang` 参数禁用 `clang`,然后将 `CC`和 `CXX`环境变量设置为你想要的. 159 | 160 | 例如使用 GCC工具链 构建: 161 | ```bash 162 | $ env CC=gcc CXX=g++ ./script/bootstrap.py -v --build_libchromiumcontent --disable_clang 163 | $ ./script/build.py -c R 164 | ``` 165 | 166 | ### 环境变量 167 | 168 | 除了 `CC` 及 `CXX`, 您还可以设置以下环境变量来自定义构建配置: 169 | 170 | * `CPPFLAGS` 171 | * `CPPFLAGS_host` 172 | * `CFLAGS` 173 | * `CFLAGS_host` 174 | * `CXXFLAGS` 175 | * `CXXFLAGS_host` 176 | * `AR` 177 | * `AR_host` 178 | * `CC` 179 | * `CC_host` 180 | * `CXX` 181 | * `CXX_host` 182 | * `LDFLAGS` 183 | 184 | 以上环境变量需要在执行 `bootstrap.py` 前设置, 在执行 `build.py` 的时候再设置将无效. -------------------------------------------------------------------------------- /development/build-instructions-osx.md: -------------------------------------------------------------------------------- 1 | # 构建说明(macOS) 2 | 3 | > 在macOS中,构建Electron 4 | 5 | ## 前提要求 6 | 7 | * macOS >= 10.11.6 8 | * [Xcode](https://developer.apple.com/technologies/tools/) >= 8.2.1 9 | * [node.js](http://nodejs.org) (外部) 10 | 11 | 如果你使用的是由Homebrew下载的Python,你还需要安装以下Python模块: 12 | 13 | * [pyobjc](https://pythonhosted.org/pyobjc/install.html) 14 | 15 | ## 获取代码 16 | 17 | ```bash 18 | $ git clone https://github.com/electron/electron 19 | ``` 20 | 21 | ## 引导 22 | 23 | 引导脚本将下载所有必需的构建依赖项并创建构建项目文件,由于使用了 `ninja`进行构建,因此不存在 `Xcode`项目. 24 | ```bash 25 | $ cd electron 26 | $ ./script/bootstrap.py -v 27 | ``` 28 | 29 | ## 构建 30 | 31 | 创建 `Release`和 `Debug` target: 32 | ```bash 33 | $ ./script/build.py 34 | ``` 35 | 36 | 还可以仅构建 `Debug` target : 37 | ```bash 38 | $ ./script/build.py -c D 39 | ``` 40 | 41 | 在构建完成后,你可以在 `out/D`下找到 `Electron.app` . 42 | 43 | ## 32位系统支持 44 | 45 | Electron仅支持在64位的macOS中构建.并不也从未计划支持32位系统. 46 | 47 | ## 清理 48 | 49 | 清理构建文件: 50 | ```bash 51 | $ npm run clean 52 | ``` 53 | 54 | 只清理`out`和`dist`目录: 55 | 56 | ```bash 57 | $ npm run clean-build 58 | ``` 59 | 60 | **注意:**以上两个clean命令都需要在构建之前再次运行 `bootstrap`。 61 | 62 | ## 相关测试 63 | 64 | 参见[构建系统概述:测试](build-system-overview.md#tests) -------------------------------------------------------------------------------- /development/build-instructions-windows.md: -------------------------------------------------------------------------------- 1 | # 构建说明(Windows) 2 | 3 | > 在Windows中,构建Electron 4 | 5 | ## 前提要求 6 | 7 | * Windows 7/Server 2008 R2或者更高的版本 8 | * Visual Studio 2015 Update 3 - [免费下载VS 2015社区版](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) 9 | * [Python 2.7](http://www.python.org/download/releases/2.7/) (已实践证明的一点的是该版本的Python安装后重启电脑才可使用!) 10 | * [Node.js](http://nodejs.org/download/) 11 | * [Git](http://git-scm.com) 12 | * [Windows调试工具](https://msdn.microsoft.com/en-us/library/windows/hardware/ff551063.aspx) 13 | 14 | 假如需要创建一个完整发行版,则使用 `symstore.exe`在`.pdb`文件中新建符号存储. 15 | 16 | 如果你现在还没有安装 Windows , [modern.ie](https://www.modern.ie/en-us/virtualization-tools#downloads) 有一个 timebombed 版本的 Windows ,你可以用它来构建 Electron. 17 | 18 | Building Electron完全使用命令行脚本完成,您可以使用任何编辑器开发Electron,但不能使用Visual Studio完成(将来可能支持)。 19 | 20 | **注意:**即使Visual Studio不用于构建,但它仍然是**必须的**,因为我们需要它提供的构建工具链。 21 | 22 | ## 获取代码 23 | 24 | ```powershell 25 | $ git clone https://github.com/electron/electron.git 26 | ``` 27 | 28 | ## 引导 29 | 30 | 引导脚本将下载所有必需的构建依赖项并创建构建项目文件,由于使用了 `ninja`进行构建,因此不存在 `Visual Studio`项目. 31 | ```powershell 32 | $ cd electron 33 | $ python script\bootstrap.py -v 34 | ``` 35 | 36 | ## 构建 37 | 38 | 创建 `Release`和 `Debug` target: 39 | ```powershell 40 | $ python script\build.py 41 | ``` 42 | 43 | 还可以仅构建 `Debug` target : 44 | ```powershell 45 | $ python script\build.py -c D 46 | ``` 47 | 48 | 在构建完成后,你可以在 `out\D` (debug target) 或者 `out\R` (release target)下找到 `Electron.exe` . 49 | 50 | ## 32位系统支持 51 | 52 | 要构建32位目标,需要在运行引导脚本时传递 `--target_arch=ia32`参数: 53 | ```powershell 54 | $ python script\bootstrap.py -v --target_arch=ia32 55 | ``` 56 | 57 | ## Visual Studio项目 58 | 59 | 要生成Visual Studio项目,可以传递 `--msvs`参数: 60 | ```powershell 61 | $ python script\bootstrap.py --msvs 62 | ``` 63 | 64 | ## 清理 65 | 66 | 清理构建文件: 67 | ```powershell 68 | $ npm run clean 69 | ``` 70 | 71 | 只清理`out`和`dist`目录: 72 | 73 | ```bash 74 | $ npm run clean-build 75 | ``` 76 | 77 | **注意:**以上两个clean命令都需要在构建之前再次运行 `bootstrap`。 78 | 79 | ## 相关测试 80 | 81 | 参见[构建系统概述:测试](build-system-overview.md#tests) 82 | 83 | ## 故障排除 84 | 85 | ### 未找到命令xxxx 86 | 87 | 遇到如 `Command xxxx not found`之类错误, 你可以尝试使用 `VS2015命令提示`控制台来执行构建脚本 88 | 89 | ### 致命内部编译器错误:C1001 90 | 91 | 确保您已安装最新的Visual Studio 92 | 93 | ### Assertion failed: ((handle))->activecnt >= 0 94 | 95 | 如果在 Cygwin 下构建的,你可能会看到 `bootstrap.py` 失败并且附带下面错误 : 96 | ``` 97 | Assertion failed: ((handle))->activecnt >= 0, file src\win\pipe.c, line 1430 98 | 99 | Traceback (most recent call last): 100 | File "script/bootstrap.py", line 87, in 101 | sys.exit(main()) 102 | File "script/bootstrap.py", line 22, in main 103 | update_node_modules('.') 104 | File "script/bootstrap.py", line 56, in update_node_modules 105 | execute([NPM, 'install']) 106 | File "/home/zcbenz/codes/raven/script/lib/util.py", line 118, in execute 107 | raise e 108 | subprocess.CalledProcessError: Command '['npm.cmd', 'install']' returned non-zero exit status 3 109 | ``` 110 | 111 | 这是由同时使用 Cygwin Python 和 Win32 Node 造成的 bug.解决办法就是使用 Win32 Python 执行 引导脚本 (假设你已经在目录 `C:\Python27` 下安装了 Python): 112 | 113 | ```powershell 114 | $ /cygdrive/c/Python27/python.exe script/bootstrap.py 115 | ``` 116 | 117 | ### LNK1181: cannot open input file 'kernel32.lib' 118 | 119 | 重新安装 32位的 Node.js. 120 | 121 | ### Error: ENOENT, stat 'C:\Users\USERNAME\AppData\Roaming\npm' 122 | 123 | 创建一个一样的目录 ,[应该可以解决问题](http://stackoverflow.com/a/25095327/102704). 124 | 125 | ```powershell 126 | $ mkdir ~\AppData\Roaming\npm 127 | ``` 128 | 129 | ### node-gyp is not recognized as an internal or external command 130 | 131 | 如果你使用 Git Bash 来构建,或许会遇到这个错误,可以使用 PowerShell 或 VS2015 Command Prompt 来代替 . 132 | -------------------------------------------------------------------------------- /development/build-system-overview.md: -------------------------------------------------------------------------------- 1 | # 构建系统概述 2 | 3 | Electron使用[gyp](https://gyp.gsrc.io/)进行项目生成,使用[ninja](https://ninja-build.org/)进行构建。项目配置可以在 `.gyp`和 `.gypi`文件中找到。 4 | 5 | ## Gyp文件 6 | 7 | 下面的 `gyp`文件包含了构建Electron的主要规则: 8 | 9 | * `electron.gyp`定义了Electron本身是如何构建的。 10 | * `common.gypi`调整Node的构建配置,使其与Chromium一起构建。 11 | * `brightray/brightray.gyp`定义`brightray`是如何构建的,并包含与Chromium关联的默认配置。 12 | * `brightray/brightray.gypi`包括关于构建的一般构建配置。 13 | 14 | ## 组件构建 15 | 16 | 由于Chromium是一个相当大的项目,最终的连接阶段可能需要几分钟,这使得开发变得困难。 17 | 18 | 为了解决这个问题,Chromium引入了 `组件构建`,它将每个组件构建为一个单独的共享库,使得链接非常快,但牺牲了文件大小和性能。 19 | 20 | 在Electron中,我们采用了一个非常相似的方法: 21 | 22 | 对于 `Debug`构建,二进制将链接到共享库版本的Chromium组件,以实现快速链接时间; 23 | 24 | 对于 `Release`构建,二进制将链接到静态库版本,所以我们可以有最好的二进制大小和性能。 25 | 26 | ##最小引导 27 | 28 | 运行引导脚本时,会下载所有Chromium的预构建二进制文件( `libchromiumcontent`)。默认情况下,将下载静态库和共享库,最终大小应在800MB和2GB之间,具体取决于平台。 29 | 30 | 默认情况下, `libchromiumcontent`是从Amazon Web Services下载的。 31 | 32 | 如果设置了 `LIBCHROMIUMCONTENT_MIRROR`环境变量,引导脚本将从中下载。 33 | 34 | [`libchromiumcontent-qiniu-mirror`](https://github.com/hokein/libchromiumcontent-qiniu-mirror)是 `libchromiumcontent`的镜像。 35 | 36 | 如果您在访问AWS时遇到问题,可以通过 `export LIBCHROMIUMCONTENT_MIRROR = http:// 7xk3d2.dl1.z0.glb.clouddn.com /` 37 | 38 | 如果你只想快速构建Electron来进行测试或开发,可以通过传递 `--dev`参数来下载共享库版本: 39 | 40 | ```bash 41 | $ ./script/bootstrap.py --dev 42 | $ ./script/build.py -c D 43 | ``` 44 | 45 | ## 双相(Two-Phase)项目生成 46 | 47 | 在 `Release`和 `Debug`中,Electron 链接了不同配置的库。 `gyp`不支持为不同的配置配置不同的链接设置。 48 | 49 | 要解决这个问题,Electron使用 `gyp`的变量 `libchromiumcontent_component`来控制要使用的链接设置,并在运行 `gyp`时只生成一个目标。 50 | 51 | ## Target名称 52 | 53 | 与大多数项目使用 `Release`和 `Debug`作为 target名称不同,Electron使用 `R`和 `D`。 54 | 55 | 这是因为 `gyp`随机崩溃,如果只有一个 `Release`或 `Debug`构建配置被定义,Electron只需要一次生成一个目标,如上所述。 56 | 57 | 这只会影响开发人员,如果你重新构建了 Electron则不受影响。 58 | 59 | ## 相关测试 60 | 61 | 使用以下方法测试您的更改符合项目编码规范: 62 | 63 | ```bash 64 | $ npm run lint 65 | ``` 66 | 67 | 测试功能使用: 68 | ```bash 69 | $ npm test 70 | ``` 71 | 72 | 每当您对Electron源代码进行更改时,您都需要在测试之前重新运行构建: 73 | ```bash 74 | $ npm run build && npm test 75 | ``` 76 | 77 | 您可以通过使用Mocha的[独家测试](https://mochajs.org/#exclusive-tests)功能隔离您当前正在使用的特定测试或块,使测试套件运行更快。 78 | 79 | 只需将 `.only`附加到任何 `describe`或 `it`函数时调用: 80 | ```js 81 | describe.only('some feature',function(){ 82 | // ...只有在这个块中的测试才会运行 83 | }) 84 | ``` 85 | 86 | 或者,您可以使用mocha的 `grep`选项仅运行与给定的正则表达式模式匹配的测试: 87 | ```sh 88 | $ npm test - --grep child_process 89 | ``` 90 | 91 | 包含本地模块(例如`runas`)的测试不能使用调试版本执行(有关详细信息,请参阅[#2558](https://github.com/electron/electron/issues/2558)),使用发布版本。 92 | 93 | 要使用发布版本运行测试: 94 | ```bash 95 | $ npm test - -R 96 | ``` -------------------------------------------------------------------------------- /development/chromium-development.md: -------------------------------------------------------------------------------- 1 | # Chromium 开发指南 2 | 3 | > 了解并关注Chromium的开发 4 | 5 | - [Slack上的chromiumdev](https://chromiumdev-slack.herokuapp.com) 6 | - [在Twitter上@ChromiumDev](https://twitter.com/ChromiumDev) 7 | - [在Twitter上@googlechrome](https://twitter.com/googlechrome) 8 | - [博客](https://blog.chromium.org) 9 | - [代码搜索](https://cs.chromium.org/) 10 | - [源代码](https://cs.chromium.org/chromium/src/) 11 | - [发展和近况](https://www.chromium.org/developers/calendar) 12 | - [讨论组](http://www.chromium.org/developers/discussion-groups) 13 | 14 | 另见[V8 开发指南](v8-development.md) -------------------------------------------------------------------------------- /development/clang-format.md: -------------------------------------------------------------------------------- 1 | # 在C ++代码中使用clang-format 2 | 3 | [`clang-format`](http://clang.llvm.org/docs/ClangFormat.html) 是个自动格式化 C/C++/Objective-C 代码的工具, 可以让开发人员不需要担心代码审查期间的样式问题. 4 | 5 | 强烈建议在打开请求之前格式化已更改的C ++代码,这将节省您和审阅者的时间。 6 | 7 | 你可以通过 `npm install -g clang-format` 安装 `clang-format` 和 `git-clang-format`. 8 | 9 | 根据 Electron C++ 代码样式自动格式化文件, 只要运行 `clang-format -i path/to/electron/file.cc` 即可. 它应该能够在 macOS/Linux/Windows 上运行. 10 | 11 | 格式化已更改代码的工作流程: 12 | 13 | 1. 在Electron存储库中更改代码 14 | 2. 运行 `git add your_changed_file.cc`. 15 | 3. 运行 `git-clang-format`, 然后你将可能会看到修改后的 `your_changed_file.cc`, 这些修改是从 `clang-format` 生成的. 16 | 4. 运行 `git add your_changed_file.cc`, 并提交你的修改. 17 | 5. 现在, 准备好的分支推送请求已经被打开. 18 | 19 | 如果你想在你最新的 git commit(HEAD)中格式化更改的代码, 你可以运行 `git-clang-format HEAD~1`. 通过 `git-clang-format -h` 可以获得更多详情. 20 | 21 | ## 编辑器集成 22 | 23 | 您还可以将 `clang-format`直接集成到您喜欢的编辑器中。有关设置编辑器集成的更多指导,请参阅以下页面: 24 | * [Atom](https://atom.io/packages/clang-format) 25 | * [Vim & Emacs](http://clang.llvm.org/docs/ClangFormat.html#vim-integration) -------------------------------------------------------------------------------- /development/coding-style.md: -------------------------------------------------------------------------------- 1 | # 编码规范 2 | 3 | > 以下是 Electron 项目的编码规范,您可以运行 `npm run lint`来显示 `cpplint`和 `eslint`检测到的任何规范问题 4 | 5 | ## C++ 和 Python 6 | 7 | 对于C ++和Python,我们遵循Chromium的[编码风格](http://www.chromium.org/developers/coding-style). 您可以使用[clang-format](clang-format.md)自动格式化C ++代码.也可以使用 `script/cpplint.py` 来检验文件是否符合要求. 8 | 9 | 我们目前使用的 Python 版本是 Python 2.7. 10 | 11 | C++ 代码中用到了许多 Chromium 中的接口和数据类型,因此建议你能熟悉它们.Chromium 中的[重要接口和数据结构](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures)就是一篇不错的入门文档,里面提到了一些特殊类型、域内类型(退出作用域时自动释放内存)、日志机制,等等. 12 | 13 | ## JavaScript 14 | 15 | * 书写 [标准的JavaScript代码风格](http://npm.im/standard). 16 | 17 | 18 | * 文件名使用 `-` 而不是 `_` 来连接单词,比如 `file-name.js` 而不是 `file_name.js`,这是沿用 [github/atom](https://github.com/github/atom) 模块的命名方式(`module-name`).这条规则仅适用于 `.js` 文件. 19 | * 在适当的地方使用较新的ES6/ES2015语法 20 | * [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) - 规定的或其他常量 21 | * [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) - 用于定义变量 22 | * [Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)- 而不是`function(){}` 23 | * [Template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) - 而不是字符串连接使用`+` 24 | 25 | ## 命名方式 26 | 27 | Electron API使用与Node.js相同的大小写方案: 28 | 29 | - 当模块是一个类似 `BrowserWindow`的类,用 `CamelCase`. 30 | - 当模块是一组类似 `globalShortcut`的API,用 `mixCase`. 31 | - 当API是一个复杂的对象属性,例如 `win.webContents`, 用 `mixedCase`. 32 | - 非模块API则使用自然标题,如 ` Tag` 或 `Process Object`. 33 | 34 | 当新建一个 API 时,我们倾向于使用 getters 和 setters 而不是 jQuery 单函数的命名方式,比如 `.getText()` 和 `.setText(text)` ,而不是 `.text([text])`.这里有关于该规则的[讨论记录](https://github.com/electron/electron/issues/46). -------------------------------------------------------------------------------- /development/debug-instructions-windows.md: -------------------------------------------------------------------------------- 1 | # 在 Windows 中调试 2 | 3 | 如果你在 Electron 中遇到问题或者引起崩溃,你认为它不是由你的JavaScript应用程序引起的,而是由 Electron 本身引起的。调试可能有点棘手,特别是对于不习惯 native/C++ 调试的开发人员。 4 | 5 | 然而,使用 Visual Studio,GitHub托管的 Electron Symbol Server 和Electron 源代码,在 Electron 的源代码中启用断点调试是相当容易的。 6 | 7 | ## 要求 8 | 9 | * **Electron 的调试版本**: 最简单的方法是自己构建它,使用 [Windows 的构建说明](build-instructions-windows.md) 中列出的工具和先决条件要求。虽然你可以轻松地附加和调试 Electron,因为你可以直接下载它,你会发现,由于大量的优化,使调试实质上更加困难:调试器将无法向您显示所有变量的内容,并且执行路径可能看起来很奇怪,这是因为内联,尾部调用和其他编译器已经过优化。 10 | 11 | * **Visual Studio 与 C++ 工具**: Visual Studio 2013 和 Visual Studio 2015 的免费社区版本都可以使用。 安装之后, [配置 Visual Studio 使用 GitHub 的 Electron Symbol 服务器](setting-up-symbol-server.md). 它将使 Visual Studio 能够更好地理解 Electron 中发生的事情,从而更容易以人类可读的格式呈现变量。 12 | 13 | * **ProcMon**: [免费的 SysInternals 工具][sys-internals] 允许您检查进程参数,文件句柄和注册表操作。 14 | 15 | ## 附加并调试 Electron 16 | 17 | 要启动调试会话,请打开 PowerShell/CMD 并执行 Electron 的调试版本,使用应用程序作为参数打开。 18 | 19 | ```powershell 20 | $ ./out/D/electron.exe ~/my-electron-app/ 21 | ``` 22 | 23 | ### 设置断点 24 | 25 | 然后,打开 Visual Studio。 Electron 不是使用 Visual Studio 构建的,因此不包含项目文件 - 但是您可以打开源代码文件 "As File",这意味着 Visual Studio 将自己打开它们。 26 | 27 | 您仍然可以设置断点 - Visual Studio 将自动确定源代码与附加过程中运行的代码相匹配,并相应地中断。 28 | 29 | 相关的代码文件可以在 `./atom/` 以及 Brightray 中找到, 找到 `./brightray/browser` 和 `./brightray/common`. 30 | 31 | 如果是内核,你也可以直接调试 Chromium,这显然在 `chromium_src` 中。 32 | 33 | ### 附加 34 | 35 | 您可以将 Visual Studio 调试器附加到本地或远程计算机上正在运行的进程。 进程运行后,单击 调试 / 附加 到进程(或按下 `CTRL+ALT+P`)打开“附加到进程”对话框。 36 | 37 | 您可以使用此功能调试在本地或远程计算机上运行的应用程序,同时调试多个进程。 38 | 39 | 如果Electron在不同的用户帐户下运行,请选中“显示所有用户的进程”复选框。 请注意,根据您的应用程序打开的浏览器窗口数量,您将看到多个进程。 40 | 41 | 典型的单窗口应用程序将导致 Visual Studio 向您提供两个 `Electron.exe` 条目 - 一个用于主进程,一个用于渲染器进程。 因为列表只给你的名字,目前没有可靠的方法来弄清楚哪个是。 42 | 43 | ### 我应该附加哪个进程? 44 | 45 | 在主进程内部执行的代码(即在主 JavaScript 文件中找到或最终运行的代码)以及使用远程代码调用的代码(`require('electron').remote`)将在主进程内运行,而其他代码将在其相应的渲染器进程内执行。 46 | 47 | 您可以在调试时附加到多个程序,但在任何时候只有一个程序在调试器中处于活动状态。 您可以在 `调试位置` 工具栏或 `进程窗口` 中设置活动程序。 48 | 49 | ## 使用 ProcMon 观察进程 50 | 51 | 虽然 Visual Studio 非常适合检查特定的代码路径,但 ProcMon 的优势在于它可以监视应用程序对操作系统的所有操作 - 捕获进程的文件,注册表,网络,进程和分析详细信息。 52 | 53 | 它试图记录发生的 **所有** 事件,并且可能是相当压倒性的,而且果你想了解你的应用程序对操作系统做什么和如何做,它则是一个很有价值的资源。 54 | 55 | 有关 ProcMon 的基本和高级调试功能的介绍,请查看Microsoft提供的[视频教程][procmon-instructions]。 56 | 57 | [sys-internals]: https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx 58 | [procmon-instructions]: https://channel9.msdn.com/shows/defrag-tools/defrag-tools-4-process-monitor 59 | -------------------------------------------------------------------------------- /development/debugging-instructions-macos.md: -------------------------------------------------------------------------------- 1 | # 在 macOS 中调试 2 | 3 | 如果你在Electron中遇到崩溃或问题并且你认为它不是由你的JavaScript应用程序引起的,而是由Electron本身引起的,调试起来可能有点棘手,特别是对于不习惯native / C ++调试的开发人员. 4 | 5 | 然而,使用lldb和Electron源代码,在Electron的源代码中使用断点启用逐步调试是相当容易的. 6 | 7 | ## 要求 8 | 9 | * **Electron 的调试版本**: 最简单的方法是使用[macOS的构建说明](build-instructions-osx.md)中列出的工具和先决条件. 10 | 11 | 因为Electron本身经过大量优化,这使调试变得更加困难:因为内联,尾部调用和其他编译器优化,调试器将无法显示所有变量的内容和执行路径可以看起来很奇怪. 12 | 13 | * **Xcode**: 除了Xcode,还要安装Xcode命令行工具. 14 | 它们包括LLDB,在Mac OS X上的Xcode中的默认调试器.它支持在桌面和iOS设备和模拟器上调试C,Objective-C和C ++. 15 | 16 | ## 附加并调试 Electron 17 | 18 | 要启动调试会话,打开Terminal并启动`lldb`,传递一个调试版本的Electron作为参数. 19 | ```bash 20 | $ lldb ./out/D/Electron.app 21 | (lldb) target create "./out/D/Electron.app" 22 | Current executable set to './out/D/Electron.app' (x86_64). 23 | ``` 24 | 25 | ### 设置断点 26 | 27 | LLDB是一个强大的工具,支持进行多种策略的代码检查. 在这做一个基本的介绍,让我们假设你从 JavaScript 调用一个不正常的命令 - 所以你想打断该命令的 C++ 对应的 Electron 源. 28 | 29 | 相关的代码文件可以在 `./atom/` 以及 Brightray 中找到, 找到 `./brightray/browser` 和 `./brightray/common`. 如果是内核,你也可以直接调试 Chromium,这显然在 `chromium_src` 中. 30 | 31 | 让我们假设你想调试 `app.setName()`, 在 `browser.cc` 中定义为 `Browser::SetName()`. 使用 `breakpoint` 命令进行断点,指定文件和断点位置: 32 | ```bash 33 | (lldb) breakpoint set --file browser.cc --line 117 34 | Breakpoint 1: where = Electron Framework`atom::Browser::SetName(std::__1::basic_string, std::__1::allocator > const&) + 20 at browser.cc:118, address = 0x000000000015fdb4 35 | ``` 36 | 37 | 然后, 启动 Electron: 38 | 39 | ```bash 40 | (lldb) run 41 | ``` 42 | 43 | 应用程式会立即暂停,因为 Electron 会在启动时设定应用程序名称: 44 | 45 | ```bash 46 | (lldb) run 47 | Process 25244 launched: '/Users/fr/Code/electron/out/D/Electron.app/Contents/MacOS/Electron' (x86_64) 48 | Process 25244 stopped 49 | * thread #1: tid = 0x839a4c, 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 50 | frame #0: 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118 51 | 115 } 52 | 116 53 | 117 void Browser::SetName(const std::string& name) { 54 | -> 118 name_override_ = name; 55 | 119 } 56 | 120 57 | 121 int Browser::GetBadgeCount() { 58 | (lldb) 59 | ``` 60 | 61 | 显示当前帧的参数和局部变量, 运行 `frame variable` (或 `fr v`), 这将显示你的应用程序当前设置名称为 `Electron`. 62 | ```bash 63 | (lldb) frame variable 64 | (atom::Browser *) this = 0x0000000108b14f20 65 | (const string &) name = "Electron": { 66 | [...] 67 | } 68 | ``` 69 | 70 | 在当前选择的线程中执行源级单步执行, 执行 `step` (或 `s`). 这将带你进入 `name_override_.empty()`. 继续前进,步过,运行 `next` (或 `n`). 71 | ```bash 72 | (lldb) step 73 | Process 25244 stopped 74 | * thread #1: tid = 0x839a4c, 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119, queue = 'com.apple.main-thread', stop reason = step in 75 | frame #0: 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119 76 | 116 77 | 117 void Browser::SetName(const std::string& name) { 78 | 118 name_override_ = name; 79 | -> 119 } 80 | 120 81 | 121 int Browser::GetBadgeCount() { 82 | 122 return badge_count_; 83 | ``` 84 | 85 | 要完成此时的调试,运行 `process continue`. 你也可以继续,直到这个线程中的某一行被命中( `线程直到100`). 此命令将在当前帧中运行线程,直到它到达此帧中的行100,或者如果它离开当前帧,则停止. 86 | 87 | 现在,如果你打开 Electron 的开发工具并调用 `setName`,你将再次命中断点. 88 | 89 | ### 进一步阅读 90 | LLDB是一个有着丰富文档的强大的工具,请参考 Apple 的调试文档,了解更多信息 例如 [LLDB命令结构参考][lldb-command-structure] 或 [使用LLDB作为独立调试器][lldb-standalone]. 91 | 92 | 你也可以查看LLDB的 [手册和教程][lldb-tutorial], 它将解释更复杂的调试场景. 93 | 94 | [lldb-command-structure]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-basics.html#//apple_ref/doc/uid/TP40012917-CH2-SW2 95 | [lldb-standalone]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-terminal-workflow-tutorial.html 96 | [lldb-tutorial]: http://lldb.llvm.org/tutorial.html 97 | -------------------------------------------------------------------------------- /development/setting-up-symbol-server.md: -------------------------------------------------------------------------------- 1 | # 在调试器中设置符号服务器 2 | > 调试符号允许您有更好的调试会话sessions 3 | 4 | 他们有关于可执行文件和动态库中包含的函数的信息,并为您提供获取干净的调用堆栈的信息。 5 | 6 | 符号服务器允许调试器自动加载正确的符号,二进制文件和源文件,而不强制用户下载大型调试文件。服务器的功能类似[Microsoft的符号服务器](http://support.microsoft.com/kb/311503) 7 | 8 | 请注意,因为已发布的Electron版本已大量优化,调试并不总是容易。调试器将无法向您显示所有变量的内容,并且执行路径可能看起来很奇怪,因为内联,尾调用和其他编译器已经过优化。 9 | 10 | 唯一的解决方法是构建未优化的本地构建。 11 | 12 | Electron的官方符号服务器网址为https://electron-symbols.githubapp.com。您无法直接访问此URL,而是必须将其添加到调试工具的符号路径。 13 | 14 | 在下面的示例中,使用本地缓存目录来避免从服务器重复提取PDB。用机器上合适的缓存目录替换 `c:\code\symbols` 15 | 16 | ## 在Windbg中使用符号服务器 17 | 18 | > Windbg符号路径使用以星号字符分隔的字符串值配置 19 | 20 | 要仅使用Electron符号服务器,请将以下条目添加到符号路径(**注意:**如果您希望使用其他位置下载符号,您可以用计算机上的任何可写目录替换 `c:\code\symbols`): 21 | 22 | ``` 23 | SRV*c:\code\symbols\*https://electron-symbols.githubapp.com 24 | ``` 25 | 26 | 在环境中使用Windbg菜单或通过键入 `.sympath`命令将此字符串设置为 `_NT_SYMBOL_PATH`。 27 | 28 | 如果你也想从微软的符号服务器获取符号,你应该先进行列出: 29 | ``` 30 | SRV*c:\code\symbols\*http://msdl.microsoft.com/download/symbols;SRV*c:\code\symbols\*https://electron-symbols.githubapp.com 31 | ``` 32 | 33 | ## 在Visual Studio中使用符号服务器 34 | 35 | 36 | 37 | 38 | ## 故障排除:符号将无法加载 39 | 40 | 在Windbg中键入以下命令以输出为什么符号未加载: 41 | ``` 42 | > !sym noisy 43 | > .reload /f electron.exe 44 | ``` 45 | -------------------------------------------------------------------------------- /development/source-code-directory-structure.md: -------------------------------------------------------------------------------- 1 | # 源代码目录结构 2 | 3 | > Electron 的源代码主要依据 Chromium 的拆分约定被拆成了许多部分。 4 | 5 | 为了更好地理解源代码,您可能需要了解一下 6 | [Chromium 的多进程架构](http://dev.chromium.org/developers/design-documents/multi-process-architecture) 7 | 8 | ## 源代码结构 9 | 10 | ``` 11 | Electron 12 | ├── atom/ - C ++源代码. 13 | | ├── app/ - 系统入口代码 14 | | ├── browser/ - 前端包含了主窗口、UI 和其他所有与主进程有关的东西,它会告诉渲染进程如何管理页面 15 | | | ├── ui/ - 不同平台上 UI 部分的实现 16 | | | | ├── cocoa/ - Cocoa特定的源代码 17 | | | | ├── win/ - Windows GUI特定的源代码 18 | | | | └── x/ - X11 特定的源代码 19 | | | ├── api/ - 主进程 API 的实现 20 | | | ├── net/ - 网络相关的代码 21 | | | ├── mac/ - Mac特定的Objective-C源代码 22 | | | └── resources/ -图标,平台相关的文件等 23 | | ├── renderer/ - 在渲染器进程中运行的代码 24 | | | └── api/ - 渲染器进程API的实现 25 | | └── common/ - 同时被主进程和渲染进程用到的代码,包括了一些用来将 node 的事件循环 26 | | | 整合到 Chromium 的事件循环中时用到的工具函数和代码 27 | | └── api/ - 实现常见的API,以及Electron的内置模块的基础 28 | ├── chromium_src/ - 从Chromium复制的源代码 29 | ├── default_app/ - 当Electron未启动时显示的默认应用 30 | ├── docs/ - 文档 31 | ├── lib/ - JavaScript源代码 32 | | ├── browser/ - 主进程中的Javascript初始化代码 33 | | | └── api/ - Javascript API实现. 34 | | ├── common/ - 主进程和渲染进程公用的JavaScript 35 | | | └── api/ - Javascript API实现. 36 | | └── renderer/ - 渲染进程中的Javascript初始化代码 37 | | └── api/ - Javascript API实现. 38 | ├── spec/ - 自动测试 39 | ├── electron.gyp - Electron 的构建规则 40 | └── common.gypi -为诸如 `node` 和 `breakpad` 等其他组件准备的编译设置和构建规则 41 | ``` 42 | 43 | ## 其他目录的结构 44 | 45 | * **script** - 用于诸如构建、打包、测试等开发用途的脚本 46 | * **tools** - 在 gyp 文件中用到的工具脚本,但与 `script` 目录不同, 该目录中的脚本不应该被用户直接调用 47 | * **vendor** - 第三方依赖项的源代码,为了防止人们将它与 Chromium 源码中的同名目录相混淆, 在这里我们不使用 `third_party` 作为目录名 48 | * **node_modules** - 在构建中用到的第三方 node 模块 49 | * **out** - `ninja` 的临时输出目录 50 | * **dist** - 由脚本 `script/create-dist.py` 创建的临时发布目录 51 | * **external_binaries** - 下载的不支持通过 `gyp` 构建的预编译第三方框架 52 | 53 | ## 保持Git子模块为最新 54 | 在[/vendor][vendor]目录中有一些Electron存储库的依赖项。运行 `git status`时你可能看到这样的提示: 55 | 56 | ```sh 57 | $ git status 58 | modified: vendor/libchromiumcontent (new commits) 59 | modified: vendor/node (new commits) 60 | ``` 61 | 62 | 要更新这些被提供的依赖关系,请运行以下命令: 63 | 64 | ```sh 65 | git submodule update --init --recursive 66 | ``` 67 | 68 | 如果你发现自己经常运行这个命令,你可以在你的 `~/.gitconfig`文件中为它创建一个别名: 69 | 70 | ``` 71 | [alias] 72 | su = submodule update --init --recursive 73 | ``` 74 | 75 | [vendor]: https://github.com/electron/electron/tree/master/vendor -------------------------------------------------------------------------------- /development/upgrading-chrome.md: -------------------------------------------------------------------------------- 1 | # Chrome升级清单 2 | 3 | > 概述Electron中每次升级Chrome所需的步骤 4 | 5 | 除了更新任何Chrome / Node API更改的Electron代码之外,还有这些事情需要处理: 6 | - 验证新版本的可用性 https://github.com/zcbenz/chromium-source-tarball/releases 7 | - 更新 `electron/libchromiumcontent`存储库根目录下的 `VERSION`文件 8 | - 更新 `script/update-clang.sh`里的 `CLANG_REVISION`,确保和 `libchromiumcontent/src/tools/clang/scripts/update.py`中使用的版本一致 9 | - 更新 `vendor/node`到与新版Chrome版本中使用的v8版本相对应的Node版本. 有关更多详细信息,请参阅https://nodejs.org/en/download/releases 的Node中的v8版本 10 | - 更新 `vendor/crashpad` 11 | - 更新 `vendor/depot_tools` 12 | - 更新 `libchromiumcontent` 为 `script/lib/config.py`中下载的SHA-1 13 | - 在更改的 `electron/libchromiumcontent`打开一个pull请求 14 | - 在更改的 `electron/electron`打开一个pull请求 15 | - 包括 `vendor/`中所需子模块的升级 16 | - V验证调试生成成功: 17 | - macOS 18 | - 32-bit Windows 19 | - 64-bit Window 20 | - 32-bit Linux 21 | - 64-bit Linux 22 | - ARM Linux 23 | - 验证版本构建成功: 24 | - macOS 25 | - 32-bit Windows 26 | - 64-bit Window 27 | - 32-bit Linux 28 | - 64-bit Linux 29 | - ARM Linux 30 | - 验证测试通过: 31 | - macOS 32 | - 32-bit Windows 33 | - 64-bit Window 34 | - 32-bit Linux 35 | - 64-bit Linux 36 | - ARM Linux 37 | 38 | ## 验证是否支持 `ffmpeg` 39 | 40 | Electron 的发行版已默认包含了具有专有编解码器的 `ffmpeg`. 但没有这类编解码器的版本也是与所有版本共同构建与分发的. 所以每次进行 Chrome 更新时,你都应该验证该版本是否继续支持. 41 | 42 | 通过加载以下页面可验证Electron对 `ffmpeg` 的支持.它仅仅支持使用于Electron自带的含有专有编解码器的默认 `ffmpeg`库,并不支持使用于未包含专有编解码器的 `ffmpeg`库. 43 | ```html 44 | 45 | 46 | 47 | 48 | Proprietary Codec Check 49 | 50 | 51 |

通过加载mp4(http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4)进行监测Electron是否使用了专有编解码器

52 |

53 | 54 | 67 | 68 | 69 | ``` 70 | 71 | ## 链接 72 | 73 | - [Chrome更新](https://www.chromium.org/developers/calendar) 74 | -------------------------------------------------------------------------------- /development/v8-development.md: -------------------------------------------------------------------------------- 1 | # V8 开发指南 2 | 3 | > 学习和使用V8 4 | 5 | * [V8 Tracing wiki](https://github.com/v8/v8/wiki/Tracing-V8) 6 | * [V8 Profiler wiki](https://github.com/v8/v8/wiki/V8-Profiler) - 学习分析器组合: `--prof`, `--trace-ic`, `--trace-opt`, `--trace-deopt`, `--print-bytecode`, `--print-opt-code` 7 | * [V8 Interpreter Design](https://docs.google.com/document/d/11T2CRex9hXxoJwbYqVQ32yIPMh0uouUZLdyrtmMoL44/edit?ts=56f27d9d#heading=h.6jz9dj3bnr8t) 8 | * [Optimizing compiler](https://github.com/v8/v8/wiki/TurboFan) 9 | * [V8 GDB Debugging](https://github.com/v8/v8/wiki/GDB-JIT-Interface) 10 | 11 | 另见[Chromium 开发指南](chromium-development.md) -------------------------------------------------------------------------------- /faq.md: -------------------------------------------------------------------------------- 1 | # 常见问题 2 | >除了官方内容外,还直接集合了各种常见方法,适用于初学者和懒癌; 3 | 4 | ## Electron何时将Chrome升级为最新版本? 5 | 6 | 通常会在stable(稳定)版的Chrome发布后的两周内,不过由于工作量的问题,该时间并不能完全保证. 7 | 8 | 虽然我们只使用了稳定版Chrome,但是beta 或 dev 版中发布了重要的更新或修复时,我们会立即打上这个补丁. 9 | 10 | 更多细节,参考[安全,本地功能和你的责任](tutorial/security.md)_注意,该章节译者尚未精校,目前使用中文官译本_ 11 | 12 | ## Electron何时将Node.js升级为最新版本? 13 | 14 | 通常会在最新版Node.js发布一个月之后,以此来避免Node.js刚发布后的常见bug. 15 | 16 | Node.js的新特性一般是由V8升级引起的,由于Electron使用的是Chrome浏览器内置的V8,所以Electron中常常内置了新 Node.js 才有的部分特性. 17 | 18 | 19 | ## 如何在两个网页间共享数据? 20 | 要在网页(渲染器进程)之间共享数据,最简单的方法是使用浏览器中已经可以使用的HTML5 API,如[Storage API][storage], [`localStorage`][local-storage], [`sessionStorage`][session-storage], 和 [IndexedDB][indexed-db]. 21 | 22 | 你也可以利用Electron的IPC机制实现,先将主进程中的对象存储为全局变量,再通过 `electron`模块的 `remote`属性从渲染器访问它们. 23 | ```javascript 24 | // 在主进程中 25 | global.sharedObject = { 26 | someProperty: 'default value' 27 | } 28 | ``` 29 | 30 | ```javascript 31 | // 在第一个页面中 32 | require('electron').remote.getGlobal('sharedObject').someProperty = 'new value' 33 | ``` 34 | 35 | ```javascript 36 | // 在第二个页面中 37 | console.log(require('electron').remote.getGlobal('sharedObject').someProperty) 38 | ``` 39 | 40 | ## 为什么应用窗口或托盘图标在一段时间后消失不见了? 41 | 42 | 这是因为用于存储窗口和托盘的变量被垃圾回收了,更多细节请阅读以下文章: 43 | * [Memory Management][memory-management] 44 | * [Variable Scope][variable-scope] 45 | 46 | 47 | 如果你只是需要快速修复这个问题的话,你可以通过下面的方式更改变量作用域,以避免这个变量被垃圾回收. 48 | 49 | 示例: 50 | 51 | ```javascript 52 | const {app, Tray} = require('electron') 53 | app.on('ready', () => { 54 | const tray = new Tray('/path/to/icon.png') 55 | tray.setTitle('hello world') 56 | }) 57 | ``` 58 | 59 | 改成: 60 | 61 | ```javascript 62 | const {app, Tray} = require('electron') 63 | //let的作用即防止被垃圾回收 64 | let tray = null 65 | app.on('ready', () => { 66 | tray = new Tray('/path/to/icon.png') 67 | tray.setTitle('hello world') 68 | }) 69 | ``` 70 | 71 | ## 为什么在Electron中无法使用jQuery/RequireJS/Meteor/AngularJS ? 72 | 73 | 由于Electron集成了Node.js,所以在DOM中插入某些额外变量,比如 `module`, `exports`, `require`.等等. 这将导致许多库不能正常运行,因为它们也要插入同名变量。 74 | 75 | 我们可以通过禁用 Node.js 来解决这个问题: 76 | 77 | ```javascript 78 | // 主进程中 79 | const {BrowserWindow} = require('electron') 80 | let win = new BrowserWindow({ 81 | webPreferences: { 82 | nodeIntegration: false 83 | } 84 | }) 85 | win.show() 86 | ``` 87 | 88 | 但是,如果你仍然需要Node.js 和 Electron 的 API,那么你在引入那些库之前将这些变量重命名,比如: 89 | 90 | ```html 91 | 92 | 99 | 100 | 101 | ``` 102 | 103 | 或者使用这个: 104 | 105 | ```html 106 | 107 | 108 | ``` 109 | 110 | ## 为什么 `require('electron').xxx` 结果是 undefined ? 111 | 112 | 使用Electron的内置模块时,你可能会遇到如下错误: 113 | 114 | ``` 115 | > require('electron').webFrame.setZoomFactor(1.0) 116 | Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined 117 | ``` 118 | 119 | 这是由于你在项目或全局中已安装了[npm `electron` 模块][electron-module],这些模块把Electron内置模块覆盖了. 120 | 121 | 你可以输出`electron`模块的路径来验证是否使用了正确的内置模块: 122 | 123 | ```javascript 124 | console.log(require.resolve('electron')) 125 | ``` 126 | 127 | 然后,再检查一下格式是否是这样子的: 128 | 129 | ``` 130 | "/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js" 131 | ``` 132 | 133 | 如果输出的路径类似 `node_modules/electron/index.js`,那么你需要移除或重名npm的 `electron`模块. 134 | 135 | ```bash 136 | npm uninstall electron 137 | npm uninstall -g electron 138 | ``` 139 | 如果问题依旧.你可能需要仔细检查一下拼写或可能在错误的进程中使用了该模块.比如 `electron.app`只能在主进程中使用,而 `electron.webFrame`只能在渲染进程使用. 140 | 141 | 142 | 143 | ## 有哪些asar文件常用命令? 144 | 145 | asar文件常用命令,所在目录运行以下命令: 146 | 147 | ``` 148 | 安装:$ npm install asar -g 149 | 压缩:$ asar pack app app.asar 150 | 解压:$ asar extract app.asar testpath 151 | ``` 152 | 153 | 更多asar用法,请移步[应用分发](tutorial/application-distribution.md) 154 | 155 | ## Electron是否可以创建可全透明并可穿透的窗口? 156 | 目前Electron有两个不足: 157 | 158 | 第一即无法创建可穿透的透明窗口(虽然可以通过禁用加速来实现,但得不偿失),这样限制了前台异形UI的发展。 159 | 160 | 第二点即尚未支持或以后可能也不支持对移动端平台的支持,只能是自己绕着路子的实现,这样也就增加了开发成本。 161 | 162 | 163 | ## Electron自带的托盘右键菜单过丑,如何自定义托盘右键菜单? 164 | 165 | Tray模块调用的是系统菜单,牺牲UI但强调了实用性.如果需要自定义菜单,有许多此类Node模块.此类问题你只需记得Electron不仅可以使用自身API创建相关内容,也可以充分利用Node API或相关模块,可以无限拓展. 166 | 167 | ![image](demo/images/03.png) 168 | 169 | 当然你还可以使用以下方式轻松实现: 170 | 171 | ![image](demo/images/trayWindow.png) 172 | 173 | [memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management 174 | [variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx 175 | [electron-module]: https://www.npmjs.com/package/electron 176 | [storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage 177 | [local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage 178 | [session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage 179 | [indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API -------------------------------------------------------------------------------- /glossary.md: -------------------------------------------------------------------------------- 1 | # 专业术语 2 | > 本文介绍了Electron开发时常用的专业属于. 3 | 4 | ### ASAR 5 | > 含义:**ASAR即Atom Shell 程序包** 6 | 7 | [asar][asar]类似常用的 `tar` 格式文件,Electron 无需解压即可读取其中的文件。 8 | 9 | [asar的使用方法](https://github.com/electron/asar),通常用来将文档打包在一个.asar中,防止js,html,css等文件直接暴露在外. 10 | 11 | 简单例子: 12 | ``` 13 | 安装:$ npm install asar -g 14 | 压缩:$ asar pack app app.asar 15 | 解压:$ asar extract app.asar testpath 16 | ``` 17 | 18 | ### Brightray 19 | > 含义:**一个专为Electron开发的可将 [libchromiumcontent] 应用到程序中的静态库** 20 | 21 | ### DMG 22 | > 含义:**苹果系统的磁盘镜像打包格式** 23 | 24 | DMG文件通常用于分发应用程序的 `installers`(安装包)。[electron-builder] 支持使用 `dmg` 来作为编译目标。 25 | 26 | ### IPC 27 | > 含义:**进程间通信** 28 | 29 | Electron 使用 IPC 来在 [主进程] 和 [渲染进程] 之间传递 JSON 信息。 30 | 31 | 主进程与渲染进程的ipc通信例子: 32 | ``` 33 | //主进程中ipcMain监听(on)了事件asynchronous-message并传回给渲染层中的asynchronous-reply. 34 | const ipcMain = require('electron').ipcMain; 35 | ipcMain.on('asynchronous-message', function(event, arg) { 36 | console.log(arg); // 输出 `ping` 37 | event.sender.send('asynchronous-reply', 'pong'); 38 | }); 39 | 40 | ipcMain.on('synchronous-message', function(event, arg) { 41 | console.log(arg); // 输出 `ping` 42 | event.returnValue = 'pong'; 43 | }); 44 | // 渲染进程中发送(send)了ping给asynchronous-message并监听了asynchronous-reply. 45 | const ipcRenderer = require('electron').ipcRenderer; 46 | console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // 输出 `pong` 47 | 48 | ipcRenderer.on('asynchronous-reply', function(event, arg) { 49 | console.log(arg); // 输出 `pong` 50 | }); 51 | ipcRenderer.send('asynchronous-message', 'ping'); 52 | ``` 53 | 54 | ### libchromiumcontent 55 | > 含义:**一个单独的开源库,包含了 Chromium 的模块及其所有依赖(比如 Blink, [V8] 等)** 56 | 57 | ### 主进程 58 | > 含义:**主进程,通常是指 `main.js` 文件,是每个Electron程序的入口点** 59 | 60 | 它全程控制着整个 APP 的生命周期,也管理着比如菜单,菜单栏,Dock,托盘等元素,也负责创建 APP 的每个渲染进程,而且整个 Node API 都集成在里面。 61 | 62 | 主进程在 `package.json` 中的 `main` 属性当中定义,这也是为什么 `electron .` 能够知道应该使用哪个文件来启动。 63 | 64 | 参见: [进程](#进程), [渲染进程](#渲染进程) 65 | 66 | ### MAS 67 | > 含义:**Mac App Store 的缩略词** 68 | 69 | 关于如何提交你的 app 至 MAS ,详见 [Mac App Store Submission Guide] 。 70 | 71 | ### native modules 72 | > 含义:**原生模块是用C或C ++编写的模块,它们和普通的Node.js模块一样使用require()函数加载到Node.js或Electron中** 73 | 74 | 通常,原生模块为Node.js中运行的JavaScript和C / C ++库之间提供接口. 75 | 76 | Natural虽然支持Electron的模块,但由于Electron与Node的V8版本可能不同,所以在构建原生模块时指定 Electron headers的位置。参见: [Using Native Node Modules] 77 | 78 | 使用原生模块有以下三个方法: 79 | 80 | #### 1.最简单的方式 81 | 82 | 通过 [`electron-rebuild`][electron-rebuild]包重新编译原生模块,它帮你自动完成了下载 headers, 编译原生模块等步骤: 83 | 84 | ``` 85 | npm install --save-dev electron-rebuild 86 | ``` 87 | 88 | 每次运行`npm install`时运行这条命令: 89 | ``` 90 | ./node_modules/.bin/electron-rebuild 91 | ``` 92 | 93 | 在windows下如果上述命令遇到了问题,尝试这个: 94 | ``` 95 | .\node_modules\.bin\electron-rebuild.cmd 96 | ``` 97 | 98 | #### 2.通过 npm 安装的方式 99 | 100 | 大部分步骤和安装普通模块时一样,除了以下一些系统环境变量你需要自己操作: 101 | 102 | ``` 103 | export npm_config_disturl=https://atom.io/download/atom-shell 104 | export npm_config_target=0.33.1 105 | export npm_config_arch=x64 106 | export npm_config_runtime=electron 107 | HOME=~/.electron-gyp npm install module-name 108 | ``` 109 | 110 | #### 3.通过 node-gyp 安装 111 | 为 node-gyp 指定 Electron headers的下载路径和版本: 112 | 113 | ``` 114 | $ cd /path-to-module/ 115 | $ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=https://atom.io/download/atom-shell 116 | ``` 117 | 118 | 119 | ## NSIS 120 | > 含义:**Nullsoft Scriptable Install System缩写,它是个WIN系统的安装包制作工具** 121 | 122 | [electron-builder] 支持使用 NSIS 作为编译目标。 123 | 124 | ### 进程 125 | > 含义:**进程是正在执行的计算机程序的实例** 126 | 127 | Electron 应用同时使用了 [主进程](主进程) 和数个 [渲染进程](渲染进程)来运行多个程序。 128 | 129 | 在 Node.js 和 Electron 里面,每个运行的进程都有个 `进程` 对象。此对象是一个全局变量,提供有关当前进程的信息和控制。 130 | 131 | 参见: [主进程](#主进程), [渲染进程](#渲染进程) 132 | 133 | ### 渲染进程 134 | > 含义:**渲染进程是你的应用内的一个浏览器窗口** 135 | 136 | 与主进程不同,可以有多个这些进程,每个进程在一个单独的进程中运行.在 Node.js API 支持下,Electron 可在页面中和操作系统进行一些低级别的交互,而普通的浏览器中由于受限于沙箱环境是办不到这种交互的。 137 | 138 | 参见: [进程](#进程), [主进程](#主进程) 139 | 140 | ### Squirrel 141 | > 含义:**Electron应用程序能够在新版本发布时自动更新的一个开源框架** 142 | 143 | 详见 [autoUpdater] API 了解如何开始使用 Squirrel。 144 | 145 | ### userland 146 | > 含义:** `userland`或`userspace`都是指在操作系统内核之外运行的程​​序** 147 | 148 | 像Node一样,Electron专注于为开发多平台桌面应用程序而提供更精简必要的API。这种设计理念让 Electron 能够保持灵活而不拘束于各种规定. 149 | 150 | ### V8 151 | > 含义:**Google的一款用C ++编写的专用于Google Chrome的开源JavaScript引擎** 152 | 153 | V8可以独立运行,也可以嵌入到任何C ++应用程序中。 154 | 155 | ### webview 156 | 157 | `webview`标签用于在您的Electron应用程序中嵌入 `guest` 内容(如外部网页)。与 `iframe`不同,每个 webview 都运行在独立的进程中。 158 | 159 | 为了确保应用程序免受嵌入内容的危害, `webview`没有普通网页一样的权限,应用和嵌入内容之间的所有互动都将是异步的。 160 | 161 | [electron-rebuild]: https://github.com/paulcbetts/electron-rebuild 162 | [addons]: https://nodejs.org/api/addons.html 163 | [asar]: https://github.com/electron/asar 164 | [autoUpdater]: api/auto-updater.md 165 | [electron-builder]: https://github.com/electron-userland/electron-builder 166 | [libchromiumcontent]: #libchromiumcontent 167 | [Mac App Store Submission Guide]: tutorials/mac-app-store-submission-guide.md 168 | [主进程]: #主进程 169 | [渲染进程]: #渲染进程 170 | [Using Native Node Modules]: tutorial/using-native-node-modules.md 171 | [userland]: #userland 172 | [V8]: #v8 -------------------------------------------------------------------------------- /quick-start/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 安装成功啦! 6 | 7 | 8 |

安装成功啦!

9 | 10 | We are using Node.js , 11 | Chromium , 12 | and Electron . 13 | 14 | 15 | -------------------------------------------------------------------------------- /quick-start/main.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron') 2 | // Module to control application life. 3 | const app = electron.app 4 | // Module to create native browser window. 5 | const BrowserWindow = electron.BrowserWindow 6 | 7 | const path = require('path') 8 | const url = require('url') 9 | 10 | // Keep a global reference of the window object, if you don't, the window will 11 | // be closed automatically when the JavaScript object is garbage collected. 12 | let mainWindow 13 | 14 | function createWindow () { 15 | // Create the browser window. 16 | mainWindow = new BrowserWindow({width: 800, height: 600}) 17 | 18 | // and load the index.html of the app. 19 | mainWindow.loadURL(url.format({ 20 | pathname: path.join(__dirname, 'index.html'), 21 | protocol: 'file:', 22 | slashes: true 23 | })) 24 | 25 | // Open the DevTools. 26 | // mainWindow.webContents.openDevTools() 27 | 28 | // Emitted when the window is closed. 29 | mainWindow.on('closed', function () { 30 | // Dereference the window object, usually you would store windows 31 | // in an array if your app supports multi windows, this is the time 32 | // when you should delete the corresponding element. 33 | mainWindow = null 34 | }) 35 | } 36 | 37 | // This method will be called when Electron has finished 38 | // initialization and is ready to create browser windows. 39 | // Some APIs can only be used after this event occurs. 40 | app.on('ready', createWindow) 41 | 42 | // Quit when all windows are closed. 43 | app.on('window-all-closed', function () { 44 | // On OS X it is common for applications and their menu bar 45 | // to stay active until the user quits explicitly with Cmd + Q 46 | if (process.platform !== 'darwin') { 47 | app.quit() 48 | } 49 | }) 50 | 51 | app.on('activate', function () { 52 | // On OS X it's common to re-create a window in the app when the 53 | // dock icon is clicked and there are no other windows open. 54 | if (mainWindow === null) { 55 | createWindow() 56 | } 57 | }) 58 | 59 | // In this file you can include the rest of your app's specific main process 60 | // code. You can also put them in separate files and require them here. 61 | -------------------------------------------------------------------------------- /quick-start/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-quick-start", 3 | "version": "1.0.0", 4 | "description": "A minimal Electron application", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "electron ." 8 | }, 9 | "repository": "https://github.com/electron/electron-quick-start", 10 | "keywords": [ 11 | "Electron", 12 | "quick", 13 | "start", 14 | "tutorial", 15 | "demo" 16 | ], 17 | "author": "GitHub", 18 | "license": "CC0-1.0" 19 | } 20 | -------------------------------------------------------------------------------- /quick-start/start.bat: -------------------------------------------------------------------------------- 1 | electron . -------------------------------------------------------------------------------- /tutorial/README.md: -------------------------------------------------------------------------------- 1 | # 教程目录: 2 | * [关于 Electron](about.md) 3 | * [Electron 版本说明](electron-versioning.md) 4 | * [API弃用说明](planned-breaking-changes.md) 5 | * [快速入门](quick-start.md) 6 | * [支持的平台](supported-platforms.md) 7 | * [桌面环境集成](desktop-environment-integration.md) 8 | * [系统通知](notifications.md) 9 | * [离屏渲染](offscreen-rendering.md) 10 | * [在线/离线事件检测](online-offline-events.md) 11 | * [多线程](multithreading.md) 12 | * [REPL](repl.md) 13 | * [键盘快捷键](keyboard-shortcuts.md) 14 | * [DevTools扩展](devtools-extension.md) 15 | * [使用原生模块](using-native-node-modules.md) 16 | * [使用 Pepper Flash 插件](using-pepper-flash-plugin.md) 17 | * [使用 Selenium 和 WebDriver](using-selenium-and-webdriver.md) _(中文官译本,未精校)_ 18 | * [使用 Widevine CDM 插件](using-widevine-cdm-plugin.md) _(中文官译本,未精校)_ 19 | * [应用分发](application-distribution.md) 20 | * [应用打包](application-packaging.md) 21 | * [主进程调试](debugging-main-process.md) 22 | * [使用 node-inspector 进行主进程调试](debugging-main-process-node-inspector.md) 23 | * [使用 VSCode 进行主进程调试](debugging-main-process-vscode.md) 24 | * [Mac App Store应用提交指南](mac-app-store-submission-guide.md) 25 | * [Windows App Store应用提交指南](windows-store-guide.md) _(中文官译本,未精校)_ 26 | * [安全,本地功能和你的责任](security.md) _(中文官译本,未精校)_ 27 | * [Headless CI Systems 测试](testing-on-headless-ci.md) _(中文官译本,未精校)_ -------------------------------------------------------------------------------- /tutorial/about.md: -------------------------------------------------------------------------------- 1 | # 关于 Electron 2 | [Electron](https://electron.atom.io)是一个由GitHub开发的开源库,通过将[Chromium](https://www.chromium.org/Home)和[Node.js](https://nodejs.org)组合并使用HTML,CSS和JavaScript进行构建Mac,Windows,和Linux跨平台桌面应用程序. 3 | 4 | ## 更新与维护 5 | 遇到以下情形,Electron会进行更新: 6 | * 错误修复 7 | * 新的API 8 | * Chromium或Node.js的版本更新时 9 | 10 | 由于Electron开发尚未非常成熟,目前更新的比较频繁,开发者应当及时的进行更新.[版本更新页地址](https://github.com/electron/electron/releases) 11 | 12 | ## 相关历史 13 | 14 | | :calendar: | :tada: | 15 | | --- | --- | 16 | | **2013年4月**| [启动Atom Shell项目](https://github.com/electron/electron/commit/6ef8875b1e93787fa9759f602e7880f28e8e6b45).| 17 | | **2014年5月** | [开源Atom Shell](http://blog.atom.io/2014/05/06/atom-is-now-open-source.html). | 18 | | **2015年4月** | [Atom Shell更名为Electron](https://github.com/electron/electron/pull/1389). | 19 | | **2016年5月** | [发布Electron `v1.0.0`](https://electron.atom.io/blog/2016/05/11/electron-1-0).| 20 | | **2016年5月** | [实现了Electron应用程序与Mac App Store的兼容](https://electron.atom.io/docs/tutorial/mac-app-store-submission-guide).| 21 | | **2016年8月** | [Windows应用商店支持Electron应用](https://electron.atom.io/docs/tutorial/windows-store-guide).| -------------------------------------------------------------------------------- /tutorial/application-distribution.md: -------------------------------------------------------------------------------- 1 | # 应用分发 2 | 首先,你需要下载Electron的 [prebuilt binaries](https://github.com/electron/electron/releases)进行分发. 3 | 4 | 接着,把应用所在目录命名为 `'app'`,并像下面例子一样放到Electron的 `resources`目录(macOS 中是指 `Electron.app/Contents/Resources/`,Linux 和 Windows 中是指 `resources/`)里,下面的例子是把Electron的预构建二进制文件的位置假定为 `electron/`: 5 | 6 | macOS中示例: 7 | ```text 8 | electron/Electron.app/Contents/Resources/app/ 9 | ├── package.json 10 | ├── main.js 11 | └── index.html 12 | ``` 13 | 14 | Windows 和 Linux中示例: 15 | ```text 16 | electron/resources/app 17 | ├── package.json 18 | ├── main.js 19 | └── index.html 20 | ``` 21 | 22 | 最后,运行 `Electron.app` (Linux的 `electron`, Windows的 `electron.exe`), Electron就会作为您的应用进行启动. `electron` 目录将被部署并可以分发给用户. 23 | 24 | ## 将应用程序打包成单一文件 25 | 26 | 除了通过拷贝所有的资源文件来分发你的应用程序之外, 您还可以打包成[asar](https://github.com/electron/asar)归档以避免将源代码直接暴露给用户. 27 | 28 | 要把 `app`文件夹打包成 `asar`,你要把 `app`重命名为 `app.asar`,并像下面例子一样放到Electron的 `resources`目录,Electron就会试图读取存档并从中启动。 29 | 30 | macOS中示例: 31 | ```text 32 | electron/Electron.app/Contents/Resources/ 33 | └── app.asar 34 | ``` 35 | 36 | Windows 和 Linux中示例: 37 | ```text 38 | electron/resources/ 39 | └── app.asar 40 | ``` 41 | 42 | 更多细节详见[应用程序包](application-packaging.md). 43 | 44 | ## 更换名称与下载二进制文件 45 | 46 | 在使用 Electron 打包你的应用程序之后,你可能需要在分发给用户之前修改打包的名字。 47 | 48 | ### Windows 49 | 50 | 你可以重命名 `electron.exe`并使用类似[rcedit](https://github.com/atom/rcedit)之类的软件编辑它的图标和属性信息. 51 | 52 | ### macOS 53 | 54 | 在macOS中也可以重命名 `Electron.app`,但同时也要重命名以下两个文件中的 `CFBundleDisplayName`, `CFBundleIdentifier`和 `CFBundleName`字段: 55 | 56 | * `Electron.app/Contents/Info.plist` 57 | * `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist` 58 | 59 | 你也可以重命名 `应用帮助` 以避免在应用程序监视器中显示 `Electron Helper`,但是请确保你已经修改了 `应用帮助`的程序名称。 60 | 61 | 改过名称的应用构造示例: 62 | ``` 63 | MyApp.app/Contents 64 | ├── Info.plist 65 | ├── MacOS/ 66 | │   └── MyApp 67 | └── Frameworks/ 68 | ├── MyApp Helper EH.app 69 | | ├── Info.plist 70 | | └── MacOS/ 71 | |    └── MyApp Helper EH 72 | ├── MyApp Helper NP.app 73 | | ├── Info.plist 74 | | └── MacOS/ 75 | |    └── MyApp Helper NP 76 | └── MyApp Helper.app 77 | ├── Info.plist 78 | └── MacOS/ 79 |    └── MyApp Helper 80 | ``` 81 | 82 | ### Linux 83 | 84 | 您可以将 `electron`重命名为任何名称。 85 | 86 | ## 打包工具 87 | 88 | 除了手动打包外, 你也可以使用第三方打包工具: 89 | 90 | * [electron-builder](https://github.com/electron-userland/electron-builder) 91 | * [electron-packager](https://github.com/electron-userland/electron-packager) 92 | 93 | ## 通过重编译源代码来更换名称 94 | 95 | 你也可以直接修改和重编译 `atom.gyp` 文件,达到彻底更换Electron名称 96 | 97 | ### grunt-build-atom-shell 98 | 99 | 手动对Electron的代码修改或重编译一般都很复杂晦涩,所以可以创建一个自动处理的Grunt任务:[grunt-build-atom-shell](https://github.com/paulcbetts/grunt-build-atom-shell). 100 | 101 | 该任务会从源代码中自动处理 `.gyp` 文件并重编译应用程序的本地 Node模块以匹配这个新名称. 102 | 103 | ### 创建一个自定义 Electron 分支 104 | 105 | 如果你只是为了构建应用而已,即便是`生产级`的应用也无需创建分支,你只需使用类似 `electron-packager` 或 `electron-builder` 之类的工具即可重构Electron,而不需要去创建分支. 106 | 107 | 只有你希望将自定义C++ 代码补丁到Electron并且无法提交至upstream或被已被官方版本拒绝时,你才需要创建分支. 108 | 109 | #### 通过 surf-build 创建一个自定义版本 110 | 111 | 1. 通过npm安装[Surf](https://github.com/surf-build/surf): 112 | `npm install -g surf-build@latest` 113 | 114 | 2. 创建一个新的 S3 bucket 并按照以下结构创建文件夹: 115 | 116 | ``` 117 | - atom-shell/ 118 | - symbols/ 119 | - dist/ 120 | ``` 121 | 122 | 3. 设置以下环境变量: 123 | 124 | * `ELECTRON_GITHUB_TOKEN` - 可以在GitHub上创建发行版的令牌 125 | * `ELECTRON_S3_ACCESS_KEY`, `ELECTRON_S3_BUCKET`, `ELECTRON_S3_SECRET_KEY` - 上传 Node.js 的 headers 以及符号的位置 126 | * `ELECTRON_RELEASE` - `true`即上传部分将被运行但不设置离开, `surf-build`仅进行CI-type的检查, 适合每次运行都拉取请求. 127 | * `CI` - 必须 `true` ,否则无效. 128 | * `GITHUB_TOKEN` - 设置与 `ELECTRON_GITHUB_TOKEN`相同 129 | * `SURF_TEMP` - 在Windows上设置为 `C:\Temp` ,防止路径过长的问题. 130 | * `TARGET_ARCH` - 设置 `ia32`或 `x64` 131 | 132 | 4. 在 `script/upload.py`中,务必设置 `ELECTRON_REPO` 到你的fork(`MYORG/electron`), 尤其是你本身是Electron的贡献者. 133 | 134 | 5. `surf-build -r https://github.com/MYORG/electron -s YOUR_COMMIT -n 'surf-PLATFORM-ARCH'` 135 | 136 | 6. 可能需要等待很长时间才能完成构建. 137 | -------------------------------------------------------------------------------- /tutorial/application-packaging.md: -------------------------------------------------------------------------------- 1 | # 应用打包 2 | 3 | 为解决Windows中路径过长的问题[issues](https://github.com/joyent/node/issues/6960), 并且更快的 `require`以及简单的隐匿源码, 你可以将代码打包成 [asar][asar]. 4 | 5 | ## 打包成 `asar` 6 | 7 | [asar][asar]类似于 `tar`压缩包,它将全部文件打包至一个文件里,Electron可从中读取且无需解压整个文件. 8 | 9 | 打包成 `asar` 的两个步骤: 10 | 11 | ### 1. 安装 asar 12 | ```bash 13 | $ npm install -g asar 14 | ``` 15 | 16 | ### 2. 用 `asar pack`打包 17 | 18 | ```bash 19 | $ asar pack your-app app.asar 20 | ``` 21 | 22 | ## 使用 `asar` 23 | 24 | 在Electron中有两组API: 由Chromium提供的Node.js和Web API提供的Node API, 这两种API都支持从 `asar`中读取. 25 | 26 | ### Node API 27 | 28 | 由于 Electron 中打了特别补丁, Node API 中如 `fs.readFile` 或者 `require` 之类的方法可以将 `asar` 当作虚拟文件夹,读取 `asar` 里面的文件就和从真实的文件系统中读取一样。 29 | 30 | 假设我们在 `/path/to` 文件夹下有个 `example.asar` 包: 31 | 32 | ```bash 33 | $ asar list /path/to/example.asar 34 | /app.js 35 | /file.txt 36 | /dir/module.js 37 | /static/index.html 38 | /static/main.css 39 | /static/jquery.min.js 40 | ``` 41 | 42 | 从 `asar` 包读取一个文件: 43 | 44 | ```javascript 45 | const fs = require('fs') 46 | fs.readFileSync('/path/to/example.asar/file.txt') 47 | ``` 48 | 49 | 列出 `asar` 包中根目录下的所有文件: 50 | 51 | ```javascript 52 | const fs = require('fs') 53 | fs.readdirSync('/path/to/example.asar') 54 | ``` 55 | 56 | 使用 `asar` 包中的一个模块: 57 | 58 | ```javascript 59 | require('/path/to/example.asar/dir/module.js') 60 | ``` 61 | 62 | 您还可以使用 `BrowserWindow` 来显示一个 `asar` 包里的 web 页面: 63 | 64 | ```javascript 65 | const {BrowserWindow} = require('electron') 66 | let win = new BrowserWindow({width: 800, height: 600}) 67 | win.loadURL('file:///path/to/example.asar/static/index.html') 68 | ``` 69 | 70 | ### Web API 71 | 72 | 在 Web 页面里,用 `file:` 协议可以获取 `asar` 包中文件。和 Node API 一样,视 `asar` 包如虚拟文件夹。 73 | 74 | 例如,用 `$.get` 获取文件: 75 | 76 | ```html 77 | 83 | ``` 84 | 85 | ### 将 `asar`当成普通文件 86 | 87 | 有些场景,如:核查 `asar` 包的校验值,我们需要像读取普通文件那样读取 `asar` 包的内容(而不是当成虚拟文件夹)。 88 | 89 | 你可以使用内置的 `original-fs` (提供和 `fs` 一样的 API)模块来读取 `asar` 包的真实信息: 90 | 91 | ```javascript 92 | const originalFs = require('original-fs') 93 | originalFs.readFileSync('/path/to/example.asar') 94 | ``` 95 | 96 | 您也可以将 `process.noAsar`设置为 `true`,以禁用 `fs`模块中 `asar`的支持: 97 | ```javascript 98 | const fs = require('fs') 99 | process.noAsar = true 100 | fs.readFileSync('/path/to/example.asar') 101 | ``` 102 | 103 | ## Node API 缺陷 104 | 105 | 尽管我们已经尽了最大努力使得 `asar` 包在 Node API 下的应用尽可能的趋向于真实的目录结构,但仍有一些底层 Node API 我们无法保证其正常工作。 106 | 107 | ### `asar` 包是只读的 108 | 109 | `asar` 包中的内容不可更改,所以 Node APIs 里那些可以用来修改文件的方法在对待 `asar` 包时都无法正常工作。 110 | 111 | ### Working Directory 在 `asar` 包中无效 112 | 113 | 尽管 `asar` 包是虚拟文件夹,但其实并没有真实的目录架构对应在文件系统里,所以你不可能将 working Directory 设置成 `asar` 包里的一个文件夹。将 `asar` 中的文件夹以 `cwd` 形式作为参数传入一些 API 中也会报错。 114 | 115 | ### 对某些API进行额外的开箱 116 | 117 | 大部分 `fs` API 可以无需解压即从 `asar` 包中读取文件或者文件的信息,但是在处理一些依赖真实文件路径的底层系统方法时,Electron 会将所需文件解压到临时目录下,然后将临时目录下的真实文件路径传给底层系统方法使其正常工作。 对于这类API,耗费会略多一些。 118 | 119 | 以下是一些需要额外解压的 API: 120 | 121 | * `child_process.execFile` 122 | * `child_process.execFileSync` 123 | * `fs.open` 124 | * `fs.openSync` 125 | * `process.dlopen` - `require` native模块时用到 126 | 127 | ### `fs.stat` 获取的 stat 信息不可靠 128 | 129 | 对 `asar` 包中的文件取 `fs.stat`,返回的 `Stats` 对象不是精确值,因为这些文件不是真实存在于文件系统里。所以除了文件大小和文件类型以外,你不应该依赖 `Stats` 对象的值。 130 | 131 | ### 执行 `asar` 包中的程序 132 | 133 | Node 中有一些可以执行程序的 API,如 `child_process.exec`,`child_process.spawn` 和 `child_process.execFile` 等,但只有 `execFile` 可以执行 `asar` 包中的程序。 134 | 135 | 因为 `exec` 和 `spawn` 允许 `command` 替代 `file` 作为输入,而 `command` 是需要在 shell 下执行的,目前没有可靠的方法来判断 `command` 中是否在操作一个 `asar` 包中的文件,而且即便可以判断,我们依旧无法保证可以在无任何副作用的情况下替换 `command` 中的文件路径。 136 | 137 | ## 打包时排除文件 138 | 139 | 如上所述,一些 Node API 会在调用时将文件解压到文件系统中,除了效率问题外,也有可能引起杀毒软件的注意! 140 | 141 | 为解决这个问题,你可以在生成 `asar` 包时使用 `--unpack` 选项来排除一些文件,使其不打包到 `asar` 包中,下面是如何排除一些用作共享用途的 native 模块的方法: 142 | 143 | ```bash 144 | $ asar pack app app.asar --unpack *.node 145 | ``` 146 | 147 | 经过上述命令后,除了生成的 `app.asar` 包以外,还有一个包含了排除文件的 `app.asar.unpacked` 文件夹,你需要将这个文件夹一起拷贝,提供给用户。 148 | 149 | [asar]: https://github.com/electron/asar -------------------------------------------------------------------------------- /tutorial/debugging-main-process-node-inspector.md: -------------------------------------------------------------------------------- 1 | # 使用 node-inspector 进行主进程调试 2 | 3 | 尽管[`node-inspector`][node-inspector] 已经提供了一个熟悉的调试器 GUI 即可在 Chrome 中来调试 Electron 的主进程, 但因为 `node-inspector` 依赖于一些必须重新编译的原生 Node 模块. 4 | 5 | 所以你需要重编译所调试的Electron版本.你可以重建 `node-inspector` 依赖项, 或直接使用 [`electron-inspector`][electron-inspector] 重建.在使用 `electron-inspector`时需要注意的是,有时它可能无法修补依赖关系. 6 | 7 | 8 | ## 使用 `electron-inspector` 进行调试 9 | 10 | ### 1. 安装 [node-gyp required tools][node-gyp-required-tools] 11 | 12 | ### 2. 安装 [`electron-rebuild`][electron-rebuild] 13 | 14 | ```shell 15 | npm install electron-rebuild --save-dev 16 | ``` 17 | 18 | ### 3. 安装 [`electron-inspector`][electron-inspector] 19 | 20 | ```shell 21 | npm install electron-inspector --save-dev 22 | ``` 23 | 24 | ### 4. 启动 Electron 25 | 26 | 用 `--debug` 参数来运行 Electron: 27 | 28 | ```shell 29 | electron --debug=5858 your/app 30 | ``` 31 | 32 | 或者,在第一行暂停脚本: 33 | 34 | ```shell 35 | electron --debug-brk=5858 your/app 36 | ``` 37 | 38 | ### 5. 启动 electron-inspector 39 | 40 | 在 macOS / Linux: 41 | 42 | ```shell 43 | node_modules/.bin/electron-inspector 44 | ``` 45 | 46 | 在 Windows: 47 | 48 | ```shell 49 | node_modules\\.bin\\electron-inspector 50 | ``` 51 | 52 | `electron-inspector` 在首次运行时,或者更改了 Electron 的版本时需要重新编译 `node-inspector` 的依赖关系,重新编译的过程可能需要互联网连接,并花费一些时间才能下载 Node headers 和lib。 53 | 54 | ### 6. 加载调试器UI 55 | 56 | 在Chrome浏览器中打开http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858。如果以`--debug-brk`开头,您可能需要点击“暂停”才能强制更新UI。 57 | 58 | 59 | ## U使用`node-inspector`进行调试 60 | 61 | ### 1. 安装 [node-gyp required tools][node-gyp-required-tools] 62 | 63 | ### 2. 安装 [`node-inspector`][node-inspector] 64 | 65 | ```bash 66 | $ npm install node-inspector 67 | ``` 68 | 69 | ### 3. 安装 [`node-pre-gyp`][node-pre-gyp] 70 | 71 | ```bash 72 | $ npm install node-pre-gyp 73 | ``` 74 | 75 | ### 4. 重新编译Electron的 `node-inspector` `v8`模块 76 | 77 | **注意:** 将 target 参数修改为你的 Electron 的版本号 78 | 79 | ```bash 80 | $ node_modules/.bin/node-pre-gyp --target=1.2.5 --runtime=electron --fallback-to-build --directory node_modules/v8-debug/ --dist-url=https://atom.io/download/atom-shell reinstall 81 | $ node_modules/.bin/node-pre-gyp --target=1.2.5 --runtime=electron --fallback-to-build --directory node_modules/v8-profiler/ --dist-url=https://atom.io/download/atom-shell reinstall 82 | ``` 83 | 84 | 详见 [如何下载原生模块][how-to-install-native-modules]。 85 | 86 | ### 5. 启用Electron的调试模式 87 | 88 | 您可以使用以下参数启动Electron: 89 | 90 | ```bash 91 | $ electron --debug=5858 your/app 92 | ``` 93 | 94 | 或者,在第一行暂停脚本: 95 | 96 | ```bash 97 | $ electron --debug-brk=5858 your/app 98 | ``` 99 | 100 | ### 6. 使用 Electron 开启 [`node-inspector`][node-inspector] 服务 101 | 102 | ```bash 103 | $ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin/inspector.js 104 | ``` 105 | 106 | ### 7. 加载调试器UI 107 | 108 | 在Chrome浏览器中打开http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858。如果从 `--debug-brk`开始查看输入行,则可能需要单击暂停。 109 | 110 | [electron-inspector]: https://github.com/enlight/electron-inspector 111 | [electron-rebuild]: https://github.com/electron/electron-rebuild 112 | [node-inspector]: https://github.com/node-inspector/node-inspector 113 | [node-pre-gyp]: https://github.com/mapbox/node-pre-gyp 114 | [node-gyp-required-tools]: https://github.com/nodejs/node-gyp#installation 115 | [how-to-install-native-modules]: using-native-node-modules.md#how-to-install-native-modules 116 | -------------------------------------------------------------------------------- /tutorial/debugging-main-process-vscode.md: -------------------------------------------------------------------------------- 1 | # 使用 VSCode 进行主进程调试 2 | 3 | ### 1. 在 VSCode 中打开一个 Electron 工程。 4 | 5 | ```bash 6 | $ git clone git@github.com:electron/electron-quick-start.git 7 | $ code electron-quick-start 8 | ``` 9 | 10 | ### 2. 使用以下配置添加一个文件 `.vscode / launch.json`: 11 | 12 | ```json 13 | { 14 | "version": "0.2.0", 15 | "configurations": [ 16 | { 17 | "name": "Debug Main Process", 18 | "type": "node", 19 | "request": "launch", 20 | "cwd": "${workspaceRoot}", 21 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron", 22 | "windows": { 23 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd" 24 | }, 25 | "args" : ["."] 26 | } 27 | ] 28 | } 29 | ``` 30 | 31 | **注意:** 在 Windows 中, `runtimeExecutable` 的参数是 `"${workspaceRoot}/node_modules/.bin/electron.cmd"`。 32 | 33 | ### 3. 调试 34 | 35 | 在 `main.js` 设置断点, 并在 [Debug View](https://code.visualstudio.com/docs/editor/debugging) 中启动调试。你应该能够捕获断点信息。 36 | 37 | 这是一个预配置的项目,你可以下载并直接在 VSCode 调试: https://github.com/octref/vscode-electron-debug/tree/master/electron-quick-start -------------------------------------------------------------------------------- /tutorial/debugging-main-process.md: -------------------------------------------------------------------------------- 1 | # 主进程调试 2 | 3 | > 浏览器窗口的开发工具仅能调试渲染器的进程脚本(比如 web 页面)。Electron 提供了 `--debug` 和 `--debug-brk` 开关可以调试主进程。 4 | 5 | ## 命令行开关 6 | 7 | 使用如下的命令行开关来调试 Electron 的主进程: 8 | 9 | ### `--debug=[port]` 10 | 11 | 当这个开关用于 Electron 时,它将会监听 V8 引擎中有关 `port` 的调试器协议信息。默认的 `port` 是 `5858`。 12 | ```shell 13 | electron --debug=5858 your/app 14 | ``` 15 | 16 | ### `--debug-brk=[port]` 17 | 18 | 就像 `--debug` 一样,但是会在第一行暂停脚本运行。 19 | 20 | ## External Debuggers 21 | 22 | 如果需要使用一个支持 V8 调试器的调试协议,请参考: 23 | - [使用 VSCode 进行主进程调试](debugging-main-process-vscode.md) 24 | - [使用 node-inspector 进行主进程调试](debugging-main-process-node-inspector.md) 25 | -------------------------------------------------------------------------------- /tutorial/devtools-extension.md: -------------------------------------------------------------------------------- 1 | # DevTools扩展 2 | 3 | Electron支持[Chrome 的 DevTools 扩展][devtools-extension], 可扩展常用于调试Web的Devtools功能. 4 | 5 | ## 如何加载DevTools扩展 6 | 7 | 除了本文概述的手动加载扩展的过程,您也可以尝试从Chrome WebStore直接下载扩展的第三方工具:[electron-devtools-installer](https://github.com/GPMDP/electron-devtools-installer),. 8 | 9 | 想要Electron中加载扩展,你要先在Chrome中下载并找到它的所在路径,然后通过调用 `BrowserWindow.addDevToolsExtension(extension)` API加载它. 10 | 11 | 以[React Developer Tools][react-devtools]这个扩展为例: 12 | 13 | 1. Chrome浏览器中安装扩展. 14 | 2. Chrome导航至 `chrome://extensions`, 找到类似 `fmkadmapgofadopljbjfkapdkoienihi` 的扩展名. 15 | 3. 找出Chrome存储扩展的所在路径: 16 | * Windows中可能是:`%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions`; 17 | * Linux中可能是: 18 | * `~/.config/google-chrome/Default/Extensions/` 19 | * `~/.config/google-chrome-beta/Default/Extensions/` 20 | * `~/.config/google-chrome-canary/Default/Extensions/` 21 | * `~/.config/chromium/Default/Extensions/` 22 | * macOS中可能是: `~/Library/Application Support/Google/Chrome/Default/Extensions`. 23 | 4. 将扩展所在路径作为参数传递给 `BrowserWindow.addDevToolsExtension` API, 相对于React Developer Tools,它可能类似于: `~/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/0.15.0_0` 24 | 25 | 这样, `BrowserWindow.addDevToolsExtension`将返回扩展名, 而通过将扩展名传递给 `BrowserWindow.removeDevToolsExtension` API则进行卸载. 26 | 27 | ```bash 28 | const BrowserWindow = require('electron').remote.BrowserWindow; 29 | //返回扩展名 30 | BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome'); 31 | //卸载扩展 32 | BrowserWindow.removeDevToolsExtension('React Developer Tools'); 33 | ``` 34 | 35 | **注意:** `BrowserWindow.addDevToolsExtension` API 必须触发于ready事件之后. 36 | 37 | 38 | ## 支持的DevTools扩展 39 | 40 | 由于Electron仅支持使用了 `chrome.*` APIs的扩展, 所以那些不支持 `chrome.*` APIs的扩展可能不被支持. 41 | 42 | 以下扩展已被证实可使用在Electron中: 43 | 44 | * [Ember Inspector](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) 45 | * [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) 46 | * [Backbone Debugger](https://chrome.google.com/webstore/detail/backbone-debugger/bhljhndlimiafopmmhjlgfpnnchjjbhd) 47 | * [jQuery Debugger](https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi) 48 | * [AngularJS Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk) 49 | * [Vue.js devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) 50 | * [Cerebral Debugger](http://www.cerebraljs.com/documentation/the_debugger) 51 | * [Redux DevTools Extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd) 52 | 53 | ### DevTools扩展故障了,我该怎么办? 54 | 55 | 首先,要确保扩展仍然有作者在维护,某些无人维护的扩展甚至无法适用于最新版的Chrome,这样我们就无能为力了. 56 | 其次,在Electron[提出issues](https://github.com/electron/electron/issues)并详诉如哪个地方出现了故障等具体情况. 57 | 58 | [devtools-extension]: https://developer.chrome.com/extensions/devtools 59 | [react-devtools]: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi -------------------------------------------------------------------------------- /tutorial/electron-versioning.md: -------------------------------------------------------------------------------- 1 | # Electron 版本说明 2 | 3 | 如果你是一个经验丰富的Node开发人员,你肯定知道 `semver`或者[Semantic Versioning](http://semver.org)-也就是语义版本,即软件版本号的发布惯例。 4 | 5 | ## 语义版本控制概述 6 | 7 | 语义版本总是由三个数字组成: 8 | ``` 9 | major.minor.patch 10 | ``` 11 | 语义版本号使用以下规则解决冲突(递增): 12 | 13 | * **主要**适用于向后兼容性的更改。 14 | * **次要**适用于不破坏向后兼容性的新功能。 15 | * **补丁**是针对错误修复和其他小的更改。 16 | 17 | 记住这个方案的简单记忆如下: 18 | ``` 19 | break.feature.fix 20 | ``` 21 | 22 | ## Electron版本规则 23 | 24 | 由于对 Node 和 Chromium 的硬性依赖,Electron并不不遵循semver。因此,您应该始终引用特定版本的Electron。 25 | 26 | 版本号的使用请参照以下规则: 27 | 28 | * 主要版本: 适用于 Electron API 的突破性变更 - 如果您从 `0.37.0` 升级到 `1.0.0`, 您将需要升级您的应用程序。 29 | * 次要版本: 适用于 Chrome 主要版本 和 Node 次要版本升级; 或重大的 Electron 变动 - 如果您从 `0.37.0` 升级到 `1.0.0`, 您的应用程序仍然可以正常运行, 但你可能需要解决一些小幅的变动。 30 | * 补丁版本: 适用于新功能的添加和 bug 修复 - 如果您从 `0.37.0` 升级到 `1.0.0`, 你的应用程序仍然像之前一样正常运行。 31 | 32 | 如果你使用 `electron` 或 `electron-prebuilt`,我们建议您设置固定的版本号(如 1.1.0 而不是^1.1.0),以确保Electron的所有升级都是由您(开发人员)进行的手动操作。 33 | 34 | 例如: 35 | ```sh 36 | npm install electron --save-exact --save-dev 37 | ``` 38 | 39 | 上文 `--save-exact` 指的是在 `package.json`中配置 `electron`版本号时不带 `^`或 `〜`前缀,比如 `1.6.2`而不是 `^ 1.6.2`,以确保除非开发者手动操作,否则不进行升级. 40 | 41 | 如果你使用 `〜`为前缀,如 `〜1.6.2`,则表示锁定主次版本但允许补丁的安装. -------------------------------------------------------------------------------- /tutorial/keyboard-shortcuts.md: -------------------------------------------------------------------------------- 1 | # 键盘快捷键 2 | 3 | > 配置本地和全局键盘快捷键 4 | 5 | ## 本地快捷键 6 | 7 | 您可以使用[Menu]模块来配置仅在应用程序集中时才触发的键盘快捷键。为此,在创建[MenuItem]时务必指定[`accelerator]属性。 8 | 9 | ```js 10 | const {Menu, MenuItem} = require('electron') 11 | const menu = new Menu() 12 | 13 | menu.append(new MenuItem({ 14 | label: 'Print', 15 | accelerator: 'CmdOrCtrl+P', 16 | click: () => { console.log('打印时间') } 17 | })) 18 | ``` 19 | 20 | 可以根据用户的操作系统轻松配置不同的组合键。 21 | 22 | ```js 23 | { 24 | accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Ctrl+Shift+I' 25 | } 26 | ``` 27 | 28 | ## 全局快捷键 29 | 30 | 即使应用程序没有键盘焦点,也可以使用[globalShortcut]模块检测键盘事件。 31 | 32 | ```js 33 | const {app, globalShortcut} = require('electron') 34 | 35 | app.on('ready', () => { 36 | globalShortcut.register('CommandOrControl+X', () => { 37 | console.log('CommandOrControl+X is pressed') 38 | }) 39 | }) 40 | ``` 41 | 42 | ## BrowserWindow中的快捷键 43 | 44 | 如果要处理[BrowserWindow]的键盘快捷键,可以在渲染器进程中的窗口对象上使用 `keyup` 和 `keydown` 事件侦听器。 45 | ```js 46 | window.addEventListener('keyup', doSomething, true) 47 | ``` 48 | 注意第三个参数 `true`,这意味着监听器总是在其他监听器之前接收按键,所以它们不能对它们调用 `stopPropagation()`。 49 | 50 | 如果您不想手动进行快捷方式解析,那么有进行自动检测的库,如[mousetrap]. 51 | ```js 52 | Mousetrap.bind('4', () => { console.log('4') }) 53 | Mousetrap.bind('?', () => { console.log('show shortcuts!') }) 54 | Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup') 55 | 56 | // 组合 57 | Mousetrap.bind('command+shift+k', () => { console.log('command shift k') }) 58 | 59 | // 将多个组合映射到相同的回调 60 | Mousetrap.bind(['command+k', 'ctrl+k'], () => { 61 | console.log('command k or control k') 62 | 63 | // 返回false以防止默认行为,并阻止事件冒泡 64 | return false 65 | }) 66 | 67 | // gmail风格序列 68 | Mousetrap.bind('g i', () => { console.log('go to inbox') }) 69 | Mousetrap.bind('* a', () => { console.log('select all') }) 70 | 71 | // konami代码 72 | Mousetrap.bind('up up down down left right left right b a enter', () => { 73 | console.log('konami code') 74 | }) 75 | ``` 76 | 77 | [Menu]: ../api/menu.md 78 | [MenuItem]: ../api/menu-item.md 79 | [globalShortcut]: ../api/global-shortcut.md 80 | [`accelerator`]: ../api/accelerator.md 81 | [BrowserWindow]: ../api/browser-window.md 82 | [mousetrap]: https://github.com/ccampbell/mousetrap 83 | -------------------------------------------------------------------------------- /tutorial/multithreading.md: -------------------------------------------------------------------------------- 1 | # 多线程 2 | 3 | 使用 [Web Workers][web-workers]可以在系统级线程中运行JavaScript。 4 | 5 | ## 多线程Node.js 6 | 7 | 在 `webPreferences`中将 `n​​odeIntegrationInWorker`选项设置为 `true`,可以在Electron的Web Workers中使用Node.js功能: 8 | 9 | ```javascript 10 | let win = new BrowserWindow({ 11 | webPreferences: { 12 | nodeIntegrationInWorker: true 13 | } 14 | }) 15 | ``` 16 | 17 | 如果要把 `nodeIntegrationInWorker`独立于 `nodeIntegration` 使用, `sandbox`就不能设置为 `true`。 18 | 19 | ## 可用API 20 | 21 | WebWork虽然支持Node.js的所有内置模块,也可以使用Node.js API读取`asar`档案。但Electron的内置模块并不能在多线程环境中使用。 22 | 23 | ## 原生的 Node.js 模块 24 | 25 | 26 | 由于大多数现有的原生模块已经被假设为单线程环境,在Web Workers中使用它们可能会导致崩溃和内存损坏,所以强烈建议你不要直接将本地Node.js模块加载到Web Workers中。 27 | 28 | 还要注意的是,虽然本地Node.js模块是安全的线程,但将其加载到Web中仍然是不安全的,因为 `process.dlopen`功能并不是一个安全线程。 29 | 30 | 现在安装原生模块的唯一方法是确保应用程序在Web Workers启动后绝不加载本地模块。 31 | ```javascript 32 | process.dlopen = () => { 33 | throw new Error('Load native module is not safe') 34 | } 35 | let worker = new Worker('script.js') 36 | ``` 37 | 38 | [web-workers]: https://developer.mozilla.org/en/docs/Web/API/Web_Workers_API/Using_web_workers -------------------------------------------------------------------------------- /tutorial/notifications.md: -------------------------------------------------------------------------------- 1 | # 通知功能 (Windows, Linux, macOS) 2 | 3 | 这三个系统都为应用提供了向用户发送通知的API。 Electron允许开发人员使用[HTML5 Notification API](https://notifications.spec.whatwg.org/)快速发送通知,并通过当前系统的自带通知API来显示。 4 | 5 | **注意:** 由于这是一个HTML5 API,因此它仅在渲染器进程中可用 6 | 7 | ```javascript 8 | let myNotification = new Notification('测试标题', { 9 | body: '测试通知' 10 | }) 11 | 12 | myNotification.onclick = () => { 13 | console.log('通知已被点击') 14 | } 15 | ``` 16 | 17 | 虽然跨操作系统的代码和用户体验基本相似,但还是有一些差异。 18 | 19 | ## Windows 20 | 21 | * 在Windows 10中, 可正常通知. 22 | * 在Windows 8.1 或 Windows 8中, 需要先使用[Application User Model ID][app-user-model-id]将快捷方式创建到开始屏幕上. 23 | * 在Windows 7中, 无法使用通知. 不过你可以使用[Tray API][tray-balloon]发送一个 `气泡通知`. 24 | 25 | 另外,在Win8中,通知内容长度不超过250个字节,Windows团队建议小于200个字符.虽然Win10删除了这个限制,但是如果发送过如上千字的长文本将导致异常. 26 | 27 | ### Windows中的高级通知 28 | 29 | 最新版本的Windows支持使用图文影像元素等自定义模板的高级通知.如需使用此类通知,您可以使用[electron-windows-notifications](https://github.com/felixrieseberg/electron-windows-notifications)模块来发送 `ToastNotification` 和 `TileNotification` 对象进行实现. 30 | 31 | 仅仅通知则只需要 `electron-windows-notifications`就够了, 但是想要处理答复的话,您需要使用[`electron-windows-interactive-notifications`](https://github.com/felixrieseberg/electron-windows-interactive-notifications)模块进行注册COM组件并根据输入数据调用Electron应用来实现. 32 | 33 | ## macOS 34 | 35 | MacOS上的通知是直接转发的,但您应该了解[Apple关于通知的人机接口指南](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html) 36 | 37 | 另外,通知内容长度不超过256个字节 38 | 39 | ### macOS中的高级通知 40 | 41 | 最新版本的macOS支持发送带有快速回复的输入框的通知,如需要这一功能,请使用[node-mac-notifier](https://github.com/CharlieHess/node-mac-notifier)实现 42 | 43 | ## Windows和macOS检测系统是否支持收发通知(静默/演示模式) 44 | 45 | 您可以使用[electron-notification-state](https://github.com/felixrieseberg/electron-notification-state)模块检测系统是否允许收发通知,这样就可以避免Windows默认忽略通知的情况. 46 | 47 | ## Linux 48 | 49 | 通知使用 `libnotify`进行发送, 只要桌面环境支持 [桌面通知规范][notification-spec]即可正常显示, 包括 Cinnamon, Enlightenment, Unity, GNOME, KDE. 50 | 51 | [tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows 52 | [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx 53 | [notification-spec]: https://developer.gnome.org/notification-spec/ -------------------------------------------------------------------------------- /tutorial/offscreen-rendering.md: -------------------------------------------------------------------------------- 1 | # 离屏渲染 2 | 3 | 因为屏幕渲染可在位图中获取浏览器窗口内容,所以它可以呈现在任何地方,例如3D场景中的纹理。 4 | 5 | Electron中的屏幕渲染的使用方法与 [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef)项目类似,都可以使用两种渲染模式,并且只有脏区域在 `'paint'` 事件中传递才能更有效率。可以停止或继续渲染,还可以设置帧速率。指定的帧速率是上限值,当网页上没有发生任何事情时,不会生成任何帧。最大帧速率为60,超过60并没有任何好处,反而是性能下降。 6 | 7 | **注意:**屏幕外窗口总是创建为[无框窗口](../api/frameless-window.md). 8 | 9 | ## 两种渲染模式 10 | 11 | ### GPU加速 12 | 13 | GPU加速渲染意味着使用GPU用于合成。由于帧必须从需要更多性能的GPU中复制,因此这种模式比另一个模式慢得多,但这种模式的优点是支持WebGL和3D CSS动画。 14 | 15 | ### 软件输出设备 16 | 17 | 该模式使用软件输出设备在CPU中渲染,因此帧生成要快得多,因此该模式优于GPU加速模式。 18 | 19 | 要启用此模式,必须通过调用 [`app.disableHardwareAcceleration()`][disablehardwareacceleration] API 来禁用GPU加速。 20 | 21 | ## 使用示例 22 | 23 | ```javascript 24 | const {app, BrowserWindow} = require('electron') 25 | app.disableHardwareAcceleration() 26 | let win 27 | app.once('ready', () => { 28 | win = new BrowserWindow({ 29 | webPreferences: { 30 | offscreen: true 31 | } 32 | }) 33 | win.loadURL('http://github.com') 34 | win.webContents.on('paint', (event, dirty, image) => { 35 | // updateBitmap(dirty, image.getBitmap()) 36 | }) 37 | win.webContents.setFrameRate(30) 38 | }) 39 | ``` 40 | 41 | [disablehardwareacceleration]: ../api/app.md#appdisablehardwareacceleration -------------------------------------------------------------------------------- /tutorial/online-offline-events.md: -------------------------------------------------------------------------------- 1 | # 在线/离线事件检测 2 | 3 | 在渲染器进程中,使用标准HTML5 API实现在线和离线事件检测,例子: 4 | 5 | _main.js_ 6 | 7 | ```javascript 8 | const {app, BrowserWindow} = require('electron') 9 | 10 | let onlineStatusWindow 11 | 12 | app.on('ready', () => { 13 | onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }) 14 | onlineStatusWindow.loadURL(`file://${__dirname}/online-status.html`) 15 | }) 16 | ``` 17 | 18 | _online-status.html_ 19 | 20 | ```html 21 | 22 | 23 | 24 | 34 | 35 | 36 | ``` 37 | 38 | 你也许会希望在主程序中回应这些事件,但由于主进程中不存在`navigator`对象,所以无法直接检测在线还是离线。 39 | 40 | 不过,你可以使用Electron的进程间通信方法将事件进行转发到主进程进行处理,例子: 41 | 42 | _main.js_ 43 | 44 | ```javascript 45 | const {app, BrowserWindow, ipcMain} = require('electron') 46 | let onlineStatusWindow 47 | //ready时启用监听 48 | app.on('ready', () => { 49 | //隐藏窗口载入渲染进程,以便获取通信状态 50 | onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false }) 51 | onlineStatusWindow.loadURL(`file://${__dirname}/online-status.html`) 52 | }) 53 | //主进程中从渲染进程通信的网络状态 54 | ipcMain.on('online-status-changed', (event, status) => { 55 | console.log(status) 56 | }) 57 | ``` 58 | 59 | _online-status.html_ 60 | 61 | ```html 62 | 63 | 64 | 65 | 76 | 77 | 78 | ``` 79 | 80 | **注意:** 除了Electron未连接局域网(LAN)或路由器被视为离线(脱机)之外,其他条件都返回 `true`。 81 | 82 | 尽管如此,当 `navigator.onLine` 返回一个 `false`值时,你不能想当然的以为 `true`即已联网,因为联网状态可以轻易伪造,比如计算机使用虚拟化软件始终连接着虚拟以太网网络适配器. 83 | 84 | 所以,如果要确定 Electron的真实联网状态,您应该使用更多检查手段。 -------------------------------------------------------------------------------- /tutorial/planned-breaking-changes.md: -------------------------------------------------------------------------------- 1 | # API弃用说明 2 | 3 | 以下列表包括将在Electron 2.0中删除的API,虽然我们不确定准确的时间弃用,但我们会在至少90天前会发布警告. 4 | 5 | ## `BrowserWindow` 6 | 7 | ```js 8 | // 弃用 9 | let optionsA = {webPreferences: {blinkFeatures: ''}} 10 | let windowA = new BrowserWindow(optionsA) 11 | // 替代方案 12 | let optionsB = {webPreferences: {enableBlinkFeatures: ''}} 13 | let windowB = new BrowserWindow(optionsB) 14 | ``` 15 | 16 | ## `clipboard` 17 | 18 | ```js 19 | // 弃用 20 | clipboard.readRtf() 21 | // 替代方案 22 | clipboard.readRTF() 23 | 24 | // 弃用 25 | clipboard.writeRtf() 26 | // 替代方案 27 | clipboard.writeRTF() 28 | 29 | // 弃用 30 | clipboard.readHtml() 31 | // 替代方案 32 | clipboard.readHTML() 33 | 34 | // 弃用 35 | clipboard.writeHtml() 36 | // 替代方案 37 | clipboard.writeHTML() 38 | ``` 39 | 40 | ## `crashReporter` 41 | 42 | ```js 43 | // 弃用 44 | crashReporter.start({ 45 | companyName: 'Crashly', 46 | submitURL: 'https://crash.server.com', 47 | autoSubmit: true 48 | }) 49 | // 替代方案 50 | crashReporter.start({ 51 | companyName: 'Crashly', 52 | submitURL: 'https://crash.server.com', 53 | uploadToServer: true 54 | }) 55 | ``` 56 | 57 | ## `menu` 58 | 59 | ```js 60 | // 弃用 61 | menu.popup(browserWindow, 100, 200, 2) 62 | // 替代方案 63 | menu.popup(browserWindow, {x: 100, y: 200, positioningItem: 2}) 64 | ``` 65 | 66 | ## `nativeImage` 67 | 68 | ```js 69 | // 弃用 70 | nativeImage.toPng() 71 | // 替代方案 72 | nativeImage.toPNG() 73 | 74 | // 弃用 75 | nativeImage.toJpeg() 76 | // 替代方案 77 | nativeImage.toJPEG() 78 | 79 | // 弃用 80 | nativeImage.createFromBuffer(buffer, 1.0) 81 | // 替代方案 82 | nativeImage.createFromBuffer(buffer, { 83 | scaleFactor: 1.0 84 | }) 85 | ``` 86 | 87 | ## `process` 88 | 89 | ```js 90 | // 弃用 91 | process.versions['atom-shell'] 92 | // 替代方案 93 | process.versions.electron 94 | ``` 95 | 96 | * `process.versions.electron` and `process.version.chrome` will be made read-only properties for consistency with the other `process.versions` properties set by Node. 97 | 98 | ## `session` 99 | 100 | ```js 101 | // 弃用 102 | ses.setCertificateVerifyProc(function (hostname, certificate, callback) { 103 | callback(true) 104 | }) 105 | // 替代方案 106 | ses.setCertificateVerifyProc(function (request, callback) { 107 | callback(0) 108 | }) 109 | ``` 110 | 111 | ## `Tray` 112 | 113 | ```js 114 | // 弃用 115 | tray.setHighlightMode(true) 116 | // 替代方案 117 | tray.setHighlightMode('on') 118 | 119 | // 弃用 120 | tray.setHighlightMode(false) 121 | // 替代方案 122 | tray.setHighlightMode('off') 123 | ``` 124 | 125 | ## `webContents` 126 | 127 | ```js 128 | // 弃用 129 | webContents.openDevTools({detach: true}) 130 | // 替代方案 131 | webContents.openDevTools({mode: 'detach'}) 132 | ``` 133 | 134 | ```js 135 | // 弃用 136 | webContents.setZoomLevelLimits(1, 2) 137 | // 替代方案 138 | webContents.setVisualZoomLevelLimits(1, 2) 139 | ``` 140 | 141 | ## `webFrame` 142 | 143 | ```js 144 | // 弃用 145 | webFrame.setZoomLevelLimits(1, 2) 146 | // 替代方案 147 | webFrame.setVisualZoomLevelLimits(1, 2) 148 | 149 | // 弃用 150 | webFrame.registerURLSchemeAsSecure('app') 151 | // 替代方案 152 | protocol.registerStandardSchemes(['app'], {secure: true}) 153 | 154 | // 弃用 155 | webFrame.registerURLSchemeAsPrivileged('app', {secure: true}) 156 | // 替代方案 157 | protocol.registerStandardSchemes(['app'], {secure: true}) 158 | ``` 159 | 160 | ## `` 161 | 162 | ```js 163 | // 弃用 164 | webview.setZoomLevelLimits(1, 2) 165 | // 替代方案 166 | webview.setVisualZoomLevelLimits(1, 2) 167 | ``` 168 | 169 | ## Node Headers URL 170 | 171 | 弃用: https://atom.io/download/atom-shell 172 | 替代方案: https://atom.io/download/electron -------------------------------------------------------------------------------- /tutorial/repl.md: -------------------------------------------------------------------------------- 1 | # REPL 2 | 读取(Read)-运算(Eval)-输出(Print)-循环(Loop) (REPL) 是很简单的交互式计算机编程环境,它采用单个用户输入,运算并返回结果给用户。 `repl`模块提供了可按照以下方式访问的REPL: 3 | 4 | * 如果你的 `electron` 或 `electron-prebuilt` 已经安装为本地项目依赖项: 5 | ```sh 6 | ./node_modules/.bin/electron --interactive 7 | ``` 8 | 9 | * 如果你的 `electron` 或 `electron-prebuilt` 已经安装为全局方式: 10 | 11 | ```sh 12 | electron --interactive 13 | ``` 14 | 15 | 这里只会为主进程创建一个REPL。 您可通过调试器控制台获取渲染器进程的REPL。 16 | 17 | **注意:** `electron --interactive` 在 Windows 上不可用. 更多细节详见[Node.js REPL docs](https://nodejs.org/dist/latest/docs/api/repl.html). -------------------------------------------------------------------------------- /tutorial/security.md: -------------------------------------------------------------------------------- 1 | # 安全,本地功能和你的责任 2 | 3 | 作为 web 开发人员,我们通常喜欢网络安全性更强大的浏览器 - 与我们编写的代码相关的风险相对较小。我们的网站在沙箱中获得有限的权限,我们相信我们的用户可以享受由大量工程师团队构建的浏览器,能够快速响应新发现的安全威胁。 4 | 5 | 当使用 Electron 时,要知道 Electron 不是一个 Web 浏览器很重要。它允许您使用熟悉的 Web 技术构建功能丰富的桌面应用程序,但是您的代码具有更强大的功能。 JavaScript 可以访问文件系统,用户 shell 等。这允许您构建更高质量的本机应用程序,但是内在的安全风险会随着授予您的代码的额外权力而增加。 6 | 7 | 考虑到这一点,请注意,在 Electron 不任何处理的情况下显示来自不受信任的来源的任何内容将带来了严重的安全风险。事实上,最流行的 Electron 应用程序(Atom,Slack,Visual Studio Code 等)主要显示本地内容(或没有 Node 集成的可信安全远程内容) - 如果您的应用程序从在线源执行代码,那么您有责任确保代码不是恶意的。 8 | 9 | ## 报告安全问题 10 | 11 | 有关如何正确上报 Electron 漏洞的信息,参阅 [SECURITY.md](https://github.com/electron/electron/tree/master/SECURITY.md) 12 | 13 | ## Chromium 安全问题和升级 14 | 15 | 尽管 Electron 努力尽快支持新版本的 Chromium,但开发人员应该意识到,升级是一项严肃的工作 - 涉及手动编辑几十个甚至几百个文件。 考虑到当前的资源和贡献,Electron 通常不会是最新版本的 Chromium,总是落后于一两天或几周。 16 | 17 | 我们认为,我们当前的更新 Chromium 组件的系统在我们可用的资源和构建在框架之上的大多数应用程序的需求之间取得了适当的平衡。 我们绝对有兴趣听听更多关于在 Electron 上构建事物的人的具体用例。 非常欢迎提出请求并且捐助支持我们的努力。 18 | 19 | ## 除了以上建议 20 | 21 | 每当您从远程目标收到代码并在本地执行它时,就会存在安全问题。 举个例子,比如在浏览器窗口内显示的远程网站。 如果攻击者以某种方式设法改变所述内容(通过直接攻击源或者通过在应用和实际目的地之间进行攻击),他们将能够在用户的机器上执行本地代码。 22 | 23 | > :警告: 在任何情况下都不应该在启用了 Node 集成时加载并执行远程代码. 反而应该只使用本地文件(与应用程序一起打包)来执行 Node 代码。要显示远程内容, 应使用 `webview` 标签并确保禁用了 `nodeIntegration`. 24 | 25 | #### 检查列表 26 | 27 | 这并不是万无一失的,但至少,你应该尝试以下内容: 28 | 29 | * 只显示安全的内容(https) 30 | * 在显示远程内容的所有渲染器中禁用 Node 集成 (在 `webPreferences` 中设置 `nodeIntegration` 为 `false`) 31 | * 在显示远程内容的所有渲染器中启用上下文隔离 (在 `webPreferences` 中设置 `contextIsolation` 为 `true`) 32 | * 在所有加载远程内容的会话中使用 `ses.setPermissionRequestHandler()` . 33 | * 不要禁用 `webSecurity`. 禁用它将禁用同源策略. 34 | * 定义一个 [`Content-Security-Policy`](http://www.html5rocks.com/en/tutorials/security/content-security-policy/) 35 | , 并使用限制规则 (即: `script-src 'self'`) 36 | * 覆盖并禁用 [`eval`](https://github.com/nylas/N1/blob/0abc5d5defcdb057120d726b271933425b75b415/static/index.js#L6-L8) 37 | , 它允许字符串作为代码执行. 38 | * 不要设置 `allowRunningInsecureContent` 为 `true`. 39 | * 不要启用 `experimentalFeatures` 或 `experimentalCanvasFeatures` 除非你知道你在做什么. 40 | * 不要使用 `blinkFeatures` 除非你知道你在做什么. 41 | * WebViews: 不要填加 `nodeintegration` 属性. 42 | * WebViews: 不要使用 `disablewebsecurity` 43 | * WebViews: 不要使用 `allowpopups` 44 | * WebViews: 不要使用 `insertCSS` 或 `executeJavaScript` 操作远程 CSS/JS. 45 | * WebViews: 在 `will-attach-webview`事件之前,应验证 ``所有的选项或参数: 46 | 47 | ```js 48 | app.on('web-contents-created', (event, contents) => { 49 | contents.on('will-attach-webview', (event, webPreferences, params) => { 50 | // 未使用或已验证其位置合法性时剥离预加载脚本 51 | delete webPreferences.preload 52 | delete webPreferences.preloadURL 53 | 54 | // 禁止集成Node. 55 | webPreferences.nodeIntegration = false 56 | 57 | //验证加载中的URL. 58 | if (!params.src.startsWith('https://yourapp.com/')) { 59 | event.preventDefault() 60 | } 61 | }) 62 | }) 63 | ``` 64 | 65 | 强调一下,这份列表只是将风险降到最低,并不会完全屏蔽风险。 如果您的目的是展示一个网站,浏览器将是一个更安全的选择。 -------------------------------------------------------------------------------- /tutorial/supported-platforms.md: -------------------------------------------------------------------------------- 1 | # 支持的平台 2 | 3 | 目前 Electron 支持以下平台: 4 | 5 | ### macOS 6 | 7 | * macOS系统版本>=10.9 8 | * 仅提供64位版本的Electron. 9 | 10 | ### Windows 11 | 12 | * Windows系统版本>=7 13 | * 提供 `ia32` (x86) 和 `amd64` (x64) 版本的Electron. 14 | 15 | 需要注意的是 `ARM` 版本的 Windows 目前尚不支持。 16 | 17 | ### Linux 18 | 19 | * Ubuntu系统版本>=12.04,Fedora系统版本>=21,Debian系统版本>=8 20 | * 提供 `ia32` (x86) 和 `amd64` (x64) 版本的Electron. 21 | 22 | 预编译版本是否能够正常运行,取决于其中是否包含了编译平台的链接库。 23 | 24 | Linux中的Electron `ia32` (`i686`) 和 `x64` (`amd64`) 预编译版本均是在Ubuntu 12.04 下编译的, `arm` 版的二进制文件是在 ARM v7(硬浮点 ABI 与 25 | Debian Wheezy 版本的 NEON)下完成的。 26 | 27 | 所以只有 Ubuntu 12.04 是可以保证能正常运行的,并且以上平台已被证实可正常运行 Electron 的预编译版本. -------------------------------------------------------------------------------- /tutorial/testing-on-headless-ci.md: -------------------------------------------------------------------------------- 1 | # Headless CI Systems 测试 (Travis CI, Jenkins) 2 | 3 | Electron 基于 Chromium,所以需要一个显示驱动使其运转。如果 Chromium 无法找到一个显示驱动, 4 | ELectron 会启动失败,因此无论你如何去运行它,Electron 不会执行你的任何测试。在 Travis,Circle, 5 | Jenkins 或者类似的系统上测试基于Electron的应用时,需要进行一些配置。本质上,我们需要使用一个 6 | 虚拟的显示驱动。 7 | 8 | ## 配置虚拟显示服务器 9 | 10 | 首先安装 [Xvfb](https://en.wikipedia.org/wiki/Xvfb)。 11 | 这是一个虚拟的帧缓冲,实现了X11显示服务协议,所有的图形操作都在内存中表现,而不需要显示在 12 | 任何屏幕输出设备上。这正是我们所需要的。 13 | 14 | 然后创建一个虚拟的xvfb屏幕并且导出一个指向他的名为 `DISPLAY` 的环境变量。Electron 中的 Chromium 15 | 会自动的去寻找 `$DISPLAY`,所以你的应用不需要再去进行配置。这一步可以通过 Paul Betts 的 16 | [xvfb-maybe](https://github.com/paulcbetts/xvfb-maybe) 实现自动化:如果系统需要,在`xvfb-maybe`前加上你的测试命令 17 | 然后这个小工具会自动的设置 xvfb。在 Windows 或者 macOS 系统下,它不会执行任何东西。 18 | 19 | ``` 20 | ## 在 Windows 或者 macOS,这只是调用 electron-mocha 21 | ## 在 Linux, 如果我们在 headless 环境,这将是等同于 22 | ## xvfb-run electron-mocha ./test/*.js 23 | xvfb-maybe electron-mocha ./test/*.js 24 | ``` 25 | 26 | ### Travis CI 27 | 28 | 在 Travis 上, 你的 `.travis.yml` 应该和下面的代码相似: 29 | 30 | ```yml 31 | addons: 32 | apt: 33 | packages: 34 | - xvfb 35 | 36 | install: 37 | - export DISPLAY=':99.0' 38 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 39 | ``` 40 | 41 | ### Jenkins 42 | 43 | Jenkins下, 有一个可用的 [Xvfb插件](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin)。 44 | 45 | ### Circle CI 46 | 47 | Circle CI 是非常棒的而且有xvfb,`$DISPLAY` 也 [已经搭建,所以不需要再进行设置](https://circleci.com/docs/environment#browsers)。 48 | 49 | ### AppVeyor 50 | 51 | AppVeyor 运行于 Windows 上,支持 Selenium,Chromium,Electron 以及一些类似的工具,开箱即用,无需配置。 52 | -------------------------------------------------------------------------------- /tutorial/using-native-node-modules.md: -------------------------------------------------------------------------------- 1 | # 使用 Node 原生模块 2 | 3 | 尽管Electron支持Node 原生模块, 但Electron与Node的V8版本可能不同,所以需要在构建原生模块时指定 Electron headers的位置。 4 | 5 | ## 如何安装原生模块? 6 | 7 | 有以下三种方法: 8 | 9 | ### 第一种: 使用 `npm` 10 | 11 | 只需设置少量的系统环境变量, 你就可以使用 `npm`直接安装原生模块. 12 | 13 | 为 Electron 安装所有依赖项的一个例子: 14 | 15 | ```bash 16 | # Electron 的版本. 17 | export npm_config_target=1.2.3 18 | # Electron 的系统架构, 值为 ia32 或 x64. 19 | export npm_config_arch=x64 20 | export npm_config_target_arch=x64 21 | # 下载 Electron 的 headers. 22 | export npm_config_disturl=https://atom.io/download/electron 23 | # 告诉 node-pre-gyp 是为 Electron 构建. 24 | export npm_config_runtime=electron 25 | # 告诉 node-pre-gyp 从源代码构建模块. 26 | export npm_config_build_from_source=true 27 | # 下载所有依赖,并缓存到 ~/.electron-gyp. 28 | HOME=~/.electron-gyp npm install 29 | ``` 30 | 31 | ### 第二种: 下载并重新编译模块 32 | 33 | 你可以像普通的Node项目一样下载并安装模块, 然后通过 [`electron-rebuild`][electron-rebuild] 包重新编译原生模块,它帮你自动完成了下载 headers, 编译原生模块等步骤. 34 | 35 | 安装了 `electron-rebuild`并利用它重建模块的示例: 36 | 37 | ```bash 38 | npm install --save-dev electron-rebuild 39 | 40 | # 每次运行"npm install"时,也运行这条命令: 41 | ./node_modules/.bin/electron-rebuild 42 | 43 | # 在windows下如果上述命令遇到了问题,尝试这个: 44 | .\node_modules\.bin\electron-rebuild.cmd 45 | ``` 46 | 47 | ### 第三种: 手动编译 48 | 49 | 如果您是原生模块的作者并希望在Electron中进行测试,那么你可能需要手动重编译该Electron模块。 您可以直接使用 `node-gyp`来构建Electron: 50 | ```bash 51 | cd /path-to-module/ 52 | HOME=~/.electron-gyp node-gyp rebuild --target=1.2.3 --arch=x64 --dist-url=https://atom.io/download/electron 53 | ``` 54 | 55 | - `HOME=~/.electron-gyp` : 开发时的headers的位置. 56 | - `--target=1.2.3` : Electron的版本. 57 | - `--dist-url=...` : Electron 的 headers 的下载地址. 58 | - `--arch=x64`: 模块为适配64位操作系统而编译. 59 | 60 | ## 故障排除 61 | 62 | 你安装了原生模块后无法工作时,请尝试检查以下事项: 63 | 64 | * 模块的架构必须与Electron的架构(ia32或x64)相匹配. 65 | * 当你升级Electron后,通常也需要重编译模块. 66 | * 有疑问时,先运行 `electron-rebuild` 试试. 67 | 68 | ## `prebuild` 依赖模块 69 | 70 | [`prebuild`](https://github.com/mafintosh/prebuild) 为多个版本的 Node 和 Electron 提供了一种简单发布预编译二进制原生模块的方法。 71 | 72 | 如果为 Electron 提供二进制原生模块,请确保删除 `--build-from-source` 和 `npm_config_build_from_source` 环境变量来充分利用预编译的二进制文件。 73 | 74 | ## `node-pre-gyp` 依赖模块 75 | 76 | [`node-pre-gyp` 工具][node-pre-gyp] 提供一种部署原生 Node 预编译二进制模块的方法,很多常用模块都是使用它。 77 | 78 | 通常这些模块在 Electron 中正常工作,但当 Electron 使用比 Node 更新的 V8 版本时,ABI会被更改并引起错误 。所以一般建议从源代码编译原生模块。 79 | 80 | 如果你通过 `npm` 的方式安装模块,默认情况下这就完成了 81 | 82 | 如果没有,你需要传入 `--build-from-source` 给 `npm`, 或者设置 `npm_config_build_from_source` 环境变量。 83 | 84 | [electron-rebuild]: https://github.com/paulcbetts/electron-rebuild 85 | [node-pre-gyp]: https://github.com/mapbox/node-pre-gyp 86 | -------------------------------------------------------------------------------- /tutorial/using-pepper-flash-plugin.md: -------------------------------------------------------------------------------- 1 | # 使用 Pepper Flash 插件 2 | > 在Electron使用Pepper Flash插件,需要手动设置路径并在应用中启用它。 3 | 4 | ## 准备Flash插件的副本 5 | 6 | 在macOS和Linux上,可通过Chrome的 `chrome:// plugins`页面查看Pepper Flash插件的详细信息,接下来会用到其中的路径和版本信息,或者你也可以将其复制一份到其它位置。 7 | 8 | ## 在 Electron 中 添加支持 9 | 10 | 你可以直接添加在Electron中添加命令行: `--ppapi-flash-path` 和 `--ppapi-flash-version`,也可以在 `ready`之前调用 `app.commandLine.appendSwitch`方法. 11 | 12 | 另外,需要设置 `BrowserWindow`的 `plugins`选项(下文例子最后一行提到)。 13 | 14 | ```javascript 15 | const {app, BrowserWindow} = require('electron') 16 | const path = require('path') 17 | 18 | // 指定flash路径, 假设与main.js同一目录. 19 | let pluginName 20 | switch (process.platform) { 21 | case 'win32': 22 | pluginName = 'pepflashplayer.dll' 23 | break 24 | case 'darwin': 25 | pluginName = 'PepperFlashPlayer.plugin' 26 | break 27 | case 'linux': 28 | pluginName = 'libpepflashplayer.so' 29 | break 30 | } 31 | app.commandLine.appendSwitch('ppapi-flash-path', path.join(__dirname, pluginName)) 32 | 33 | // 可选:指定Flash版本,比如v17.0.0.169 34 | app.commandLine.appendSwitch('ppapi-flash-version', '17.0.0.169') 35 | 36 | app.on('ready', () => { 37 | let win = new BrowserWindow({ 38 | width: 800, 39 | height: 600, 40 | webPreferences: { 41 | plugins: true 42 | } 43 | }) 44 | win.loadURL(`file://${__dirname}/index.html`) 45 | // 其它 46 | }) 47 | ``` 48 | 49 | 另外,你也可以不必自己装载插件而先使用 `app.getPath('pepperFlashSystemPlugin')`获取系统自带的Pepper Flash插件路径,然后进行加载。 50 | 51 | ## 在 ``标签中启用Flash插件 52 | 53 | 将 `plugins` 属性添加到 `` 标签 54 | 55 | ```html 56 | 57 | ``` 58 | 59 | ## 故障排除 60 | 61 | 1. 当您不确定路径是否正确时,你可以在控制台中输出 `navigator.plugins`来检查是否加载了Pepper Flash插件。 62 | 2. Pepper Flash插件必须与Electron的架构相匹配,比如在Windows中常犯的错误是在64位版本的Electron使用32位版本的Flash插件. 63 | 3. 在Windows中, `--ppapi-flash-path`的路径参数必须使用 `\`作为分隔符,使用POSIX样式的路径是无效的。 64 | 4. 对于某些操作,如使用RTMP的流媒体,有必要向播放器的 `.swf`文件授予更多的权限。 实现这点的方式之一是使用 [nw-flash-trust](https://github.com/szwacz/nw-flash-trust). -------------------------------------------------------------------------------- /tutorial/using-selenium-and-webdriver.md: -------------------------------------------------------------------------------- 1 | # 使用 Selenium 和 WebDriver 2 | 3 | 引自[ChromeDriver - WebDriver for Chrome][chrome-driver]: 4 | 5 | > WebDriver 是一款开源的支持多浏览器的自动化测试工具。它提供了操作网页、用户输入、JavaScript 执行等能力。ChromeDriver 是一个实现了 WebDriver 与 Chromium 联接协议的独立服务。它也是由开发了 Chromium 和 WebDriver 的团队开发的。 6 | 7 | ## 通过 Spectron 配置 8 | 9 | [Spectron][spectron] 是 Electron 官方支持的 ChromeDriver 测试框架。 10 | 它是建立在 [WebdriverIO](http://webdriver.io/) 的顶层,并且 11 | 帮助你在测试中访问 Electron API 和绑定 ChromeDriver。 12 | 13 | ```bash 14 | $ npm install --save-dev spectron 15 | ``` 16 | 17 | ```javascript 18 | // 一个简单的测试验证一个带标题的可见的窗口 19 | var Application = require('spectron').Application 20 | var assert = require('assert') 21 | 22 | var app = new Application({ 23 | path: '/Applications/MyApp.app/Contents/MacOS/MyApp' 24 | }) 25 | 26 | app.start().then(function () { 27 | // 检查浏览器窗口是否可见 28 | return app.browserWindow.isVisible() 29 | }).then(function (isVisible) { 30 | // 验证浏览器窗口是否可见 31 | assert.equal(isVisible, true) 32 | }).then(function () { 33 | // 获得浏览器窗口的标题 34 | return app.client.getTitle() 35 | }).then(function (title) { 36 | // 验证浏览器窗口的标题 37 | assert.equal(title, 'My App') 38 | }).catch(function (error) { 39 | // 记录任何错误 40 | console.error('Test failed', error.message) 41 | }).then(function () { 42 | // 停止应用程序 43 | return app.stop() 44 | }) 45 | ``` 46 | 47 | ## 通过 WebDriverJs 配置 48 | 49 | [WebDriverJs](https://code.google.com/p/selenium/wiki/WebDriverJs) 是一个可以配合 WebDriver 做测试的 node 模块,我们会用它来做个演示。 50 | 51 | ### 1. 启动 ChromeDriver 52 | 53 | 首先,你要下载 `chromedriver`,然后运行以下命令: 54 | 55 | ```bash 56 | $ ./chromedriver 57 | Starting ChromeDriver (v2.10.291558) on port 9515 58 | Only local connections are allowed. 59 | ``` 60 | 61 | 记住 `9515` 这个端口号,我们后面会用到 62 | 63 | ### 2. 安装 WebDriverJS 64 | 65 | ```bash 66 | $ npm install selenium-webdriver 67 | ``` 68 | 69 | ### 3. 联接到 ChromeDriver 70 | 71 | 在 Electron 下使用 `selenium-webdriver` 和其平时的用法并没有大的差异,只是你需要手动设置连接 ChromeDriver,以及 Electron 的路径: 72 | 73 | ```javascript 74 | const webdriver = require('selenium-webdriver') 75 | 76 | var driver = new webdriver.Builder() 77 | // "9515" 是ChromeDriver使用的端口 78 | .usingServer('http://localhost:9515') 79 | .withCapabilities({ 80 | chromeOptions: { 81 | // 这里设置Electron的路径 82 | binary: '/Path-to-Your-App.app/Contents/MacOS/Atom' 83 | } 84 | }) 85 | .forBrowser('electron') 86 | .build() 87 | 88 | driver.get('http://www.google.com') 89 | driver.findElement(webdriver.By.name('q')).sendKeys('webdriver') 90 | driver.findElement(webdriver.By.name('btnG')).click() 91 | driver.wait(function () { 92 | return driver.getTitle().then(function (title) { 93 | return title === 'webdriver - Google Search' 94 | }) 95 | }, 1000) 96 | 97 | driver.quit() 98 | ``` 99 | 100 | ## 通过 WebdriverIO 配置 101 | 102 | [WebdriverIO](http://webdriver.io/) 也是一个配合 WebDriver 用来测试的 node 模块 103 | 104 | ### 1. 启动 ChromeDriver 105 | 106 | 首先,下载 `chromedriver`,然后运行以下命令: 107 | 108 | ```bash 109 | $ chromedriver --url-base=wd/hub --port=9515 110 | Starting ChromeDriver (v2.10.291558) on port 9515 111 | Only local connections are allowed. 112 | ``` 113 | 114 | 记住 `9515` 端口,后面会用到 115 | 116 | ### 2. 安装 WebdriverIO 117 | 118 | ```bash 119 | $ npm install webdriverio 120 | ``` 121 | 122 | ### 3. 连接到 ChromeDriver 123 | 124 | ```javascript 125 | const webdriverio = require('webdriverio') 126 | const options = { 127 | host: 'localhost', // 使用localhost作为ChromeDriver服务器 128 | port: 9515, // "9515"是ChromeDriver使用的端口 129 | desiredCapabilities: { 130 | browserName: 'chrome', 131 | chromeOptions: { 132 | binary: '/Path-to-Your-App/electron', // Electron的路径 133 | args: [/* cli arguments */] // 可选参数,类似:'app=' + /path/to/your/app/ 134 | } 135 | } 136 | } 137 | 138 | let client = webdriverio.remote(options) 139 | 140 | client 141 | .init() 142 | .url('http://google.com') 143 | .setValue('#q', 'webdriverio') 144 | .click('#btnG') 145 | .getTitle().then(function (title) { 146 | console.log('Title was: ' + title) 147 | }) 148 | .end() 149 | ``` 150 | 151 | ## 工作流程 152 | 153 | 无需重新编译 Electron,只要把 app 的源码放到 [Electron的资源目录](https://github.com/electron/electron/blob/master/docs/tutorial/application-distribution.md) 里就可直接开始测试了。 154 | 155 | 当然,你也可以在运行 Electron 时传入参数指定你 app 的所在文件夹。这步可以免去你拷贝-粘贴你的 app 到 Electron 的资源目录。 156 | 157 | [chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/ 158 | [spectron]: https://electron.atom.io/spectron 159 | -------------------------------------------------------------------------------- /tutorial/using-widevine-cdm-plugin.md: -------------------------------------------------------------------------------- 1 | # 使用 Widevine CDM 插件 2 | 3 | 在 Electron,你可以使用 Widevine CDM 插件装载 Chrome 浏览器。 4 | 5 | ## 获取插件 6 | 7 | Electron 没有为 Widevine CDM 插件配置许可 reasons,为了获得它,首先需要安装官方的 Chrome 浏览器,这匹配了体系架构和 Electron 构建使用的 Chrome 版本。 8 | 9 | __注意:__ Chrome 浏览器的主要版本必须和 Electron 使用的版本一样,否则插件不会有效,虽然 `navigator.plugins` 会显示你已经安装了它。 10 | 11 | ### Windows & macOS 12 | 13 | 在 Chrome 浏览器中打开 `chrome://components/` ,找到 `WidevineCdm` 并且确定它更新到最新版本,然后你可以从 `APP_DATA/Google/Chrome/WidevineCDM/VERSION/_platform_specific/PLATFORM_ARCH/` 路径找到所有的插件二进制文件。 14 | 15 | `APP_DATA` 是系统存放数据的地方,在 Windows 上它是 16 | `%LOCALAPPDATA%`,在 macOS 上它是 `~/Library/Application Support`. `VERSION` 是 17 | Widevine CDM 插件的版本字符串,类似 `1.4.8.866`. `PLATFORM` 是 `mac` 或 18 | `win`. `ARCH` 是 `x86` 或 `x64`。 19 | 20 | 在 Windows,必要的二进制文件是 `widevinecdm.dll` and 21 | `widevinecdmadapter.dll`,在 macOS,它们是 `libwidevinecdm.dylib` 和 22 | `widevinecdmadapter.plugin`。你可以将它们复制到任何你喜欢的地方,但是它们必须要放在一起。 23 | 24 | ### Linux 25 | 26 | 在 Linux,Chrome 浏览器将插件的二进制文件装载在一起,你可以在 `/opt/google/chrome` 下找到,文件名是 `libwidevinecdm.so` 和 27 | `libwidevinecdmadapter.so`。 28 | 29 | ## 使用插件 30 | 31 | 在获得了插件文件后,你可以使用 `--widevine-cdm-path` 命令行开关来将 `widevinecdmadapter` 的路径传递给 Electron ,插件版本使用 `--widevine-cdm-version` 开关. 32 | 33 | __注意:__ 虽然只有 `widevinecdmadapter` 的二进制文件传递给了 Electron,`widevinecdm` 二进制文件应当放在它的旁边。 34 | 35 | 必须在 `app` 模块的 `ready` 事件触发之前使用命令行开关,并且 page 使用的插件必须激活。 36 | 37 | 示例代码: 38 | 39 | ```javascript 40 | const {app, BrowserWindow} = require('electron') 41 | 42 | // 你必须通过 `widevinecdmadapter` 文件名,它是 43 | // * `widevinecdmadapter.plugin` on macOS, 44 | // * `libwidevinecdmadapter.so` on Linux, 45 | // * `widevinecdmadapter.dll` on Windows。 46 | app.commandLine.appendSwitch('widevine-cdm-path', '/path/to/widevinecdmadapter.plugin') 47 | // 插件版本可以从 Chrome 浏览器的 `chrome://plugins` 页面获得。 48 | app.commandLine.appendSwitch('widevine-cdm-version', '1.4.8.866') 49 | 50 | let win = null 51 | app.on('ready', () => { 52 | win = new BrowserWindow({ 53 | webPreferences: { 54 | // 这个 `plugins` 必须启用。 55 | plugins: true 56 | } 57 | }) 58 | win.show() 59 | }) 60 | ``` 61 | 62 | ## 验证插件 63 | 64 | 为了验证插件是否工作,你可以使用下面的方法: 65 | 66 | * 打开开发者工具查看 `navigator.plugins` 是否包含了 Widevine 67 | CDM 插件。 68 | * 打开 `https://shaka-player-demo.appspot.com/` 加载一个使用 69 | `Widevine` 的 manifest。 70 | * 打开 http://www.dash-player.com/demo/drm-test-area/,检查是否界面输出 `bitdash uses Widevine in your browser`,然后播放 video。 71 | -------------------------------------------------------------------------------- /tutorial/windows-store-guide.md: -------------------------------------------------------------------------------- 1 | # Windows商店指南 2 | 3 | 在 Windows 8 中, 一些不错的旧 win32 程序迎来了一个新朋友: 通用Windows平台(UWP)。 新的 `.appx` 格式不仅启用了许多新的强大的 API,如 Cortana 或推送通知,而且通过Windows 应用商店,也同时简化了安装和更新。 4 | 5 | Microsoft 开发了一个工具,将 Electron 应用程序[编译为 `.appx` 软件包][electron-windows-store],使开发人员能够使用新应用程序模型中的一些好东西。 本指南解释了如何使用它 - 以及 Electron AppX 包的功能和限制。 6 | 7 | ## 背景和要求 8 | 9 | Windows 10 的 "周年更新" 能够运行 win32 `.exe` 程序并且它们的虚拟化文件系统和注册表跟随一起启动。 两者都是通过在 Windows 容器中运行应用程序和安装器编译后创建的,允许 Windows 在安装过程中正确识别操作系统进行了哪些修改。 将可执行文件和虚拟文件系统与虚拟注册表配对, 允许 Windows 启用一键安装和卸载。 10 | 11 | 此外,exe 在 appx 模型内启动 - 这意味着它可以使用通用 Windows 平台可用的许多 API。 为了获得更多的功能,Electron 应用程序可以与一个看不见的 UWP 后台任务配合使用,它与 `exe` 一起启动,作为后台运行任务的接收器,接收推送通知或与其他 UWP 应用程序通信 。 12 | 13 | 要编译任何现有的 Electron 应用程序,请确保满足以下要求: 14 | 15 | * Windows 10及周年更新 (2016年8月2日发布的) 16 | * Windows 10 SDK, [这里下载][windows-sdk] 17 | * 最新的 Node 4 (运行 `node -v` 来确认) 18 | 19 | 然后, 安装 `electron-windows-store` CLI: 20 | 21 | ``` 22 | npm install -g electron-windows-store 23 | ``` 24 | 25 | ## 步骤 1: 打包你的 Electron 应用程序 26 | 27 | 打包应用程序使用 [electron-packager][electron-packager] (或类似工具). 确保在最终的应用程序中删除不需要的 `node_modules`, 因为这些你不需要模块只会额外增加你的应用程序的大小. 28 | 29 | 结构输出应该看起来大致像这样: 30 | 31 | ``` 32 | ├── Ghost.exe 33 | ├── LICENSE 34 | ├── content_resources_200_percent.pak 35 | ├── content_shell.pak 36 | ├── d3dcompiler_47.dll 37 | ├── ffmpeg.dll 38 | ├── icudtl.dat 39 | ├── libEGL.dll 40 | ├── libGLESv2.dll 41 | ├── locales 42 | │   ├── am.pak 43 | │   ├── ar.pak 44 | │   ├── [...] 45 | ├── natives_blob.bin 46 | ├── node.dll 47 | ├── resources 48 | │   ├── app 49 | │   └── atom.asar 50 | ├── snapshot_blob.bin 51 | ├── squirrel.exe 52 | ├── ui_resources_200_percent.pak 53 | ``` 54 | 55 | ## 步骤 2: 运行 electron-windows-store 56 | 57 | 从提权的 PowerShell(用管理员身份运行它)中,以所需的参数运行 `electron-windows-store`,传递输入和输出目录,应用程序的名称和版本,以及确认`node_modules`应该是扁平的。 58 | 59 | 60 | ``` 61 | electron-windows-store ` 62 | --input-directory C:\myelectronapp ` 63 | --output-directory C:\output\myelectronapp ` 64 | --flatten true ` 65 | --package-version 1.0.0.0 ` 66 | --package-name myelectronapp 67 | ``` 68 | 69 | 一旦执行,工具就开始工作:它接受您的 Electron 应用程序作为输入,展平 `node_modules`。 然后,它将应用程序归档为 `app.zip`。 使用安装程序和 Windows 容器,该工具创建一个“扩展的” AppX 包 - 包括 Windows 应用程序清单 (`AppXManifest.xml`)以及虚拟文件系统和输出文件夹中的虚拟注册表。 70 | 71 | 当创建扩展的 AppX 文件后,该工具使用 Windows App Packager(`MakeAppx.exe`)将磁盘上的这些文件创建为单文件 AppX 包。 最后,该工具可用于在计算机上创建可信证书,以签署新的 AppX 包。 使用签名的 AppX 软件包,CLI也可以自动在您的计算机上安装软件包。 72 | 73 | 74 | ## 步骤 3: 使用 AppX 包 75 | 76 | 为了运行您的软件包,您的用户将需要将 Windows 10 安装“周年纪念更新” - 有关如何更新Windows的详细信息可以在[这里][how-to-update]找到 77 | 78 | 与传统的UWP应用程序不同,打包应用程序目前需要进行手动验证过程,您可以在[这里][centennial-campaigns]申请. 79 | 在此期间,所有用户都能够通过双击安装包来安装您的程序,所以如果您只是寻找一个更简单的安装方法,可能不需要提交到商店。 80 | 81 | 在受管理的环境中(通常是企业), `Add-AppxPackage` PowerShell Cmdlet 可用于以[自动方式安装][add-appxpackage]它。 82 | 83 | 另一个重要的限制是编译的 AppX 包仍然包含一个 win32 可执行文件,因此不会在 Xbox,HoloLens 或 Phones 中运行。 84 | 85 | ## 可选: 使用 BackgroundTask 添加 UWP 功能 86 | 87 | 您可以将 Electron 应用程序与不可见的 UWP 后台任务配对,以充分利用 Windows 10 功能,如推送通知,Cortana 集成或活动磁贴。 88 | 89 | 如何使用 Electron 应用程序通过后台任务发送 Toast 通知和活动磁贴,请查看[微软提供的案例][background-task] 90 | 91 | ## 可选: 使用容器虚拟化进行转换 92 | 93 | 要生成 AppX 包,`electron-windows-store` CLI 使用的模板应该适用于大多数 Electron 应用程序。 但是,如果您使用自定义安装程序,或者您遇到生成的包的任何问题,您可以尝试使用 Windows 容器编译创建包 - 在该模式下,CLI 将在空 Windows 容器中安装和运行应用程序,以确定应用程序正在对操作系统进行哪些修改。 94 | 95 | 在运行 CLI 之前,您必须设置 “Windows Desktop App Converter” 。 这将需要几分钟,但不要担心 - 你只需要这样做一次。 从这里下载 [Desktop App Converter][app-converter] 96 | 97 | 您将得到两个文件: `DesktopAppConverter.zip` 和 `BaseImage-14316.wim`. 98 | 99 | 1. 解压 `DesktopAppConverter.zip`. 打开提权的 PowerShell (用"以管理员权限运行"打开, 确保您的系统执行策略允许我们通过调用 `Set-ExecutionPolicy bypass` 来运行我们想要运行的一切). 100 | 2. 然后, 通过调用 `.\DesktopAppConverter.ps1 -Setup -BaseImage .\BaseImage-14316.wim`, 运行 Desktop App Converter 安装,并传递 Windows 基本映像的位置 (下载的 `BaseImage-14316.wim`). 101 | 3. 如果运行以上命令提示您重新启动,请重新启动计算机,并在成功重新启动后再次运行上述命令。 102 | 103 | 当安装成功后,您可以继续编译你的 Electron 应用程序。 104 | 105 | [windows-sdk]: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk 106 | [app-converter]: https://www.microsoft.com/en-us/download/details.aspx?id=51691 107 | [add-appxpackage]: https://technet.microsoft.com/en-us/library/hh856048.aspx 108 | [electron-packager]: https://github.com/electron-userland/electron-packager 109 | [electron-windows-store]: https://github.com/catalystcode/electron-windows-store 110 | [background-task]: https://github.com/felixrieseberg/electron-uwp-background 111 | [centennial-campaigns]: https://developer.microsoft.com/en-us/windows/projects/campaigns/desktop-bridge 112 | [how-to-update]: https://blogs.windows.com/windowsexperience/2016/08/02/how-to-get-the-windows-10-anniversary-update 113 | --------------------------------------------------------------------------------