# app
`app` 模塊是為了控制整個應用的生命周期設計的。
下面的這個例子將會展示如何在最后一個窗口被關閉時退出應用:
```javascript
var app = require('app');
app.on('window-all-closed', function() {
app.quit();
});
```
## 事件列表
`app` 對象會觸發以下的事件:
### 事件:'will-finish-launching'
當應用程序完成基礎的啟動的時候被觸發。在 Windows 和 Linux 中,
`will-finish-launching` 事件與 `ready` 事件是相同的; 在 OS X 中,
這個時間相當于 `NSApplication` 中的 `applicationWillFinishLaunching` 提示。
你應該經常在這里為 `open-file` 和 `open-url` 設置監聽器,并啟動崩潰報告和自動更新。
在大多數的情況下,你應該只在 `ready` 事件處理器中完成所有的業務。
### 事件:'ready'
當 Electron 完成初始化時被觸發。
### 事件:'window-all-closed'
當所有的窗口都被關閉時觸發。
這個時間僅在應用還沒有退出時才能觸發。 如果用戶按下了 `Cmd + Q`,
或者開發者調用了 `app.quit()` ,Electron 將會先嘗試關閉所有的窗口再觸發 `will-quit` 事件,
在這種情況下 `window-all-closed` 不會被觸發。
### 事件:'before-quit'
返回:
* `event` Event
在應用程序開始關閉它的窗口的時候被觸發。
調用 `event.preventDefault()` 將會阻止終止應用程序的默認行為。
### 事件:'will-quit'
返回:
* `event` Event
當所有的窗口已經被關閉,應用即將退出時被觸發。
調用 `event.preventDefault()` 將會阻止終止應用程序的默認行為。
你可以在 `window-all-closed` 事件的描述中看到 `will-quit` 事件
和 `window-all-closed` 事件的區別。
### 事件:'quit'
返回:
* `event` Event
* `exitCode` Integer
當應用程序正在退出時觸發。
### 事件:'open-file' _OS X_
返回:
* `event` Event
* `path` String
當用戶想要在應用中打開一個文件時觸發。`open-file` 事件常常在應用已經打開并且系統想要再次使用應用打開文件時被觸發。
`open-file` 也會在一個文件被拖入 dock 且應用還沒有運行的時候被觸發。
請確認在應用啟動的時候(甚至在 `ready` 事件被觸發前)就對 `open-file` 事件進行監聽,以處理這種情況。
如果你想處理這個事件,你應該調用 `event.preventDefault()` 。
在 Windows系統中, 你需要通過解析 process.argv 來獲取文件路徑。
### 事件:'open-url' _OS X_
返回:
* `event` Event
* `url` String
當用戶想要在應用中打開一個url的時候被觸發。URL格式必須要提前標識才能被你的應用打開。
如果你想處理這個事件,你應該調用 `event.preventDefault()` 。
### 事件:'activate' _OS X_
返回:
* `event` Event
* `hasVisibleWindows` Boolean
當應用被激活時觸發,常用于點擊應用的 dock 圖標的時候。
### 事件:'browser-window-blur'
返回:
* `event` Event
* `window` BrowserWindow
當一個 [BrowserWindow](browser-window.md) 失去焦點的時候觸發。
### 事件:'browser-window-focus'
返回:
* `event` Event
* `window` BrowserWindow
當一個 [BrowserWindow](browser-window.md) 獲得焦點的時候觸發。
### 事件:'browser-window-created'
返回:
* `event` Event
* `window` BrowserWindow
當一個 [BrowserWindow](browser-window.md) 被創建的時候觸發。
### 事件:'certificate-error'
返回:
* `event` Event
* `webContents` [WebContents](web-contents.md)
* `url` String - URL 地址
* `error` String - 錯誤碼
* `certificate` Object
* `data` Buffer - PEM 編碼數據
* `issuerName` String - 發行者的公有名稱
* `callback` Function
當對 `url` 驗證 `certificate` 證書失敗的時候觸發,如果需要信任這個證書,你需要阻止默認行為 `event.preventDefault()` 并且
調用 `callback(true)`。
```javascript
session.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
if (url == "https://github.com") {
// 驗證邏輯。
event.preventDefault();
callback(true);
} else {
callback(false);
}
});
```
### 事件:'select-client-certificate'
返回:
* `event` Event
* `webContents` [WebContents](web-contents.md)
* `url` String - URL 地址
* `certificateList` [Object]
* `data` Buffer - PEM 編碼數據
* `issuerName` String - 發行者的公有名稱
* `callback` Function
當一個客戶端認證被請求的時候被觸發。
`url` 指的是請求客戶端認證的網頁地址,調用 `callback` 時需要傳入一個證書列表中的證書。
需要通過調用 `event.preventDefault()` 來防止應用自動使用第一個證書進行驗證。如下所示:
```javascript
app.on('select-certificate', function(event, host, url, list, callback) {
event.preventDefault();
callback(list[0]);
})
```
### 事件: 'login'
返回:
* `event` Event
* `webContents` [WebContents](web-contents.md)
* `request` Object
* `method` String
* `url` URL
* `referrer` URL
* `authInfo` Object
* `isProxy` Boolean
* `scheme` String
* `host` String
* `port` Integer
* `realm` String
* `callback` Function
當 `webContents` 要做進行一次 HTTP 登陸驗證時被觸發。
默認情況下,Electron 會取消所有的驗證行為,如果需要重寫這個行為,你需要用 `event.preventDefault()` 來阻止默認行為,并且
用 `callback(username, password)` 來進行驗證。
```javascript
app.on('login', function(event, webContents, request, authInfo, callback) {
event.preventDefault();
callback('username', 'secret');
})
```
### 事件:'gpu-process-crashed'
當 GPU 進程崩潰時觸發。
## 方法列表
`app` 對象擁有以下的方法:
**請注意** 有的方法只能用于特定的操作系統。
### `app.quit()`
試圖關掉所有的窗口。`before-quit` 事件將會最先被觸發。如果所有的窗口都被成功關閉了,
`will-quit` 事件將會被觸發,默認下應用將會被關閉。
這個方法保證了所有的 `beforeunload` 和 `unload` 事件處理器被正確執行。假如一個窗口的 `beforeunload` 事件處理器返回 `false`,那么整個應用可能會取消退出。
### `app.hide()` _OS X_
隱藏所有的應用窗口,不是最小化.
### `app.show()` _OS X_
隱藏后重新顯示所有的窗口,不會自動選中他們。
### `app.exit(exitCode)`
* `exitCode` 整數
帶著`exitCode`退出應用.
所有的窗口會被立刻關閉,不會詢問用戶。`before-quit` 和 `will-quit` 這2個事件不會被觸發
### `app.getAppPath()`
返回當前應用所在的文件路徑。
### `app.getPath(name)`
* `name` String
返回一個與 `name` 參數相關的特殊文件夾或文件路徑。當失敗時拋出一個 `Error` 。
你可以通過名稱請求以下的路徑:
* `home` 用戶的 home 文件夾(主目錄)
* `appData` 當前用戶的應用數據文件夾,默認對應:
* `%APPDATA%` Windows 中
* `$XDG_CONFIG_HOME` or `~/.config` Linux 中
* `~/Library/Application Support` OS X 中
* `userData` 儲存你應用程序設置文件的文件夾,默認是 `appData` 文件夾附加應用的名稱
* `temp` 臨時文件夾
* `exe` 當前的可執行文件
* `module` `libchromiumcontent` 庫
* `desktop` 當前用戶的桌面文件夾
* `documents` 用戶文檔目錄的路徑
* `downloads` 用戶下載目錄的路徑.
* `music` 用戶音樂目錄的路徑.
* `pictures` 用戶圖片目錄的路徑.
* `videos` 用戶視頻目錄的路徑.
### `app.setPath(name, path)`
* `name` String
* `path` String
重寫某個 `name` 的路徑為 `path`,`path` 可以是一個文件夾或者一個文件,這個和 `name` 的類型有關。
如果這個路徑指向的文件夾不存在,這個文件夾將會被這個方法創建。
如果錯誤則會拋出 `Error`。
`name` 參數只能使用 `app.getPath` 中定義過 `name`。
默認情況下,網頁的 cookie 和緩存都會儲存在 `userData` 文件夾。
如果你想要改變這個位置,你需要在 `app` 模塊中的 `ready` 事件被觸發之前重寫 `userData` 的路徑。
### `app.getVersion()`
返回加載應用程序的版本。如果應用程序的 `package.json` 文件中沒有寫版本號,
將會返回當前包或者可執行文件的版本。
### `app.getName()`
返回當前應用程序的 `package.json` 文件中的名稱。
由于 npm 的命名規則,通常 `name` 字段是一個短的小寫字符串。但是應用名的完整名稱通常是首字母大寫的,你應該單獨使用一個
`productName` 字段,用于表示你的應用程序的完整名稱。Electron 會優先使用這個字段作為應用名。
### `app.setName(name)`
* `name` String
重寫當前應用的名字
### `app.getLocale()`
返回當前應用程序的語言。
### `app.addRecentDocument(path)` _OS X_ _Windows_
* `path` String
在最近訪問的文檔列表中添加 `path`。
這個列表由操作系統進行管理。在 Windows 中您可以通過任務條進行訪問,在 OS X 中你可以通過 dock 菜單進行訪問。
### `app.clearRecentDocuments()` _OS X_ _Windows_
清除最近訪問的文檔列表。
### `app.setUserTasks(tasks)` _Windows_
* `tasks` [Task] - 一個由 Task 對象構成的數組
將 `tasks` 添加到 Windows 中 JumpList 功能的 [Tasks][tasks] 分類中。
`tasks` 中的 `Task` 對象格式如下:
`Task` Object
* `program` String - 執行程序的路徑,通常你應該說明當前程序的路徑為 `process.execPath` 字段。
* `arguments` String - 當 `program` 執行時的命令行參數。
* `title` String - JumpList 中顯示的標題。
* `description` String - 對這個任務的描述。
* `iconPath` String - JumpList 中顯示的圖標的絕對路徑,可以是一個任意包含一個圖標的資源文件。通常來說,你可以通過指明 `process.execPath` 來顯示程序中的圖標。
* `iconIndex` Integer - 圖標文件中的采用的圖標位置。如果一個圖標文件包括了多個圖標,就需要設置這個值以確定使用的是哪一個圖標。
如果這個圖標文件中只包含一個圖標,那么這個值為 0。
### `app.allowNTLMCredentialsForAllDomains(allow)`
* `allow` Boolean
動態設置是否總是為 HTTP NTLM 或 Negotiate 認證發送證書。通常來說,Electron 只會對本地網絡(比如和你處在一個域中的計算機)發
送 NTLM / Kerberos 證書。但是假如網絡設置得不太好,可能這個自動探測會失效,所以你可以通過這個接口自定義 Electron 對所有 URL
的行為。
### `app.makeSingleInstance(callback)`
* `callback` Function
這個方法可以讓你的應用在同一時刻最多只會有一個實例,否則你的應用可以被運行多次并產生多個實例。你可以利用這個接口保證只有一個實例正
常運行,其余的實例全部會被終止并退出。
如果多個實例同時運行,那么第一個被運行的實例中 `callback` 會以 `callback(argv, workingDirectory)` 的形式被調用。其余的實例
會被終止。
`argv` 是一個包含了這個實例的命令行參數列表的數組,`workingDirectory` 是這個實例目前的運行目錄。通常來說,我們會用通過將應用在
主屏幕上激活,并且取消最小化,來提醒用戶這個應用已經被打開了。
在 `app` 的 `ready` 事件后,`callback` 才有可能被調用。
如果當前實例為第一個實例,那么在這個方法將會返回 `false` 來保證它繼續運行。否則將會返回 `true` 來讓它立刻退出。
在 OS X 中,如果用戶通過 Finder、`open-file` 或者 `open-url` 打開應用,系統會強制確保只有一個實例在運行。但是如果用戶是通過
命令行打開,這個系統機制會被忽略,所以你仍然需要靠這個方法來保證應用為單實例運行的。
下面是一個簡單的例子。我們可以通過這個例子了解如何確保應用為單實例運行狀態。
```js
var myWindow = null;
var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) {
// 當另一個實例運行的時候,這里將會被調用,我們需要激活應用的窗口
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore();
myWindow.focus();
}
return true;
});
// 這個實例是多余的實例,需要退出
if (shouldQuit) {
app.quit();
return;
}
// 創建窗口、繼續加載應用、應用邏輯等……
app.on('ready', function() {
});
```
### `app.setAppUserModelId(id)` _Windows_
* `id` String
改變當前應用的 [Application User Model ID][app-user-model-id] 為 `id`.
### `app.isAeroGlassEnabled()` _Windows_
如果 [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx)(Aero Glass) 啟用
了,那么這個方法會返回 `true`,否則是 `false`。你可以用這個方法來決定是否要開啟透明窗口特效,因為如果用戶沒開啟 DWM,那么透明窗
口特效是無效的。
舉個例子:
```js
let browserOptions = {width: 1000, height: 800};
// 只有平臺支持的時候才使用透明窗口
if (process.platform !== 'win32' || app.isAeroGlassEnabled()) {
browserOptions.transparent = true;
browserOptions.frame = false;
}
// 創建窗口
win = new BrowserWindow(browserOptions);
// 轉到某個網頁
if (browserOptions.transparent) {
win.loadURL('file://' + __dirname + '/index.html');
} else {
// 沒有透明特效,我們應該用某個只包含基本樣式的替代解決方案。
win.loadURL('file://' + __dirname + '/fallback.html');
}
```
### `app.commandLine.appendSwitch(switch[, value])`
通過可選的參數 `value` 給 Chromium 中添加一個命令行開關。
**注意** 這個方法不會影響 `process.argv`,我們通常用這個方法控制一些底層 Chromium 行為。
### `app.commandLine.appendArgument(value)`
給 Chromium 中直接添加一個命令行參數,這個參數 `value` 的引號和格式必須正確。
**注意** 這個方法不會影響 `process.argv`。
### `app.dock.bounce([type])` _OS X_
* `type` String - 可選參數,可以是 `critical` 或 `informational`。默認為 `informational`。
當傳入的是 `critical` 時,dock 中的應用將會開始彈跳,直到這個應用被激活或者這個請求被取消。
當傳入的是 `informational` 時,dock 中的圖標只會彈跳一秒鐘。但是,這個請求仍然會激活,直到應用被激活或者請求被取消。
這個方法返回的返回值表示這個請求的 ID。
### `app.dock.cancelBounce(id)` _OS X_
* `id` Integer
取消這個 `id` 對應的請求。
### `app.dock.setBadge(text)` _OS X_
* `text` String
設置應用在 dock 中顯示的字符串。
### `app.dock.getBadge()` _OS X_
返回應用在 dock 中顯示的字符串。
### `app.dock.hide()` _OS X_
隱藏應用在 dock 中的圖標。
### `app.dock.show()` _OS X_
顯示應用在 dock 中的圖標。
### `app.dock.setMenu(menu)` _OS X_
* `menu` [Menu](menu.md)
設置應用的 [dock 菜單][dock-menu].
### `app.dock.setIcon(image)` _OS X_
* `image` [NativeImage](native-image.md)
設置應用在 dock 中顯示的圖標。
[dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103
[tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
- 介紹
- 常見問題
- Electron 常見問題
- 向導
- 支持平臺
- 分發應用
- 提交應用到 Mac App Store
- 打包應用
- 使用 Node 原生模塊
- 主進程調試
- 使用 Selenium 和 WebDriver
- 使用開發人員工具擴展
- 使用 Pepper Flash 插件
- 使用 Widevine CDM 插件
- 教程
- 快速入門
- 桌面環境集成
- 在線/離線事件探測
- API文檔
- 簡介
- 進程對象
- 支持的 Chrome 命令行開關
- 環境變量
- 自定義的 DOM 元素
- File 對象
- <webview> 標簽
- window.open 函數
- 在主進程內可用的模塊
- app
- autoUpdater
- BrowserWindow
- contentTracing
- dialog
- globalShortcut
- ipcMain
- Menu
- MenuItem
- powerMonitor
- powerSaveBlocker
- protocol
- session
- webContents
- Tray
- 在渲染進程(網頁)內可用的模塊
- desktopCapturer
- ipcRenderer
- remote
- webFrame
- 在兩種進程中都可用的模塊
- clipboard
- crashReporter
- nativeImage
- screen
- shell
- 開發
- 代碼規范
- 源碼目錄結構
- 與 NW.js(原 node-webkit)在技術上的差異
- 構建系統概覽
- 構建步驟(OS X)
- 構建步驟(Windows)
- 構建步驟(Linux)
- 在調試中使用 Symbol Server