Electron2

Author Avatar
A Man Has No Name 5月 26, 2017
  • 在其它设备中阅读本文章

第二部分

App

1
2
3
4
const {app} = require('electron')
app.on('window-all-closed', () => {
app.quit()
})

Events

  • will-finish-launching
    windows 和 linux中,与 ready 一样。

    在mac中,NSApplication 中的 applicationWillFinishLaunching 通知。一般此时可以创建open-file 和 open-url的监听事件,和开启 崩溃日志,以及自动更新。

    但是,大多数时候,你不需要管这一步, 也不需要做什么。

  • ready

    • 在mac中 会返回lanchInfo的信息
      一切初始化完成之后,到这里。在mac中,如果是从消息中心打开的,那么可以调用,app.isReady()来检查是不是都已经准备好。
  • window-all-closed
    如果用户,执行Cmd + Q, 活着开发者直接调用app.quit(), 会直接出发will-quit, 但是,but,就不会不会触发这个事件

  • befor-quit

    • 返回 Event
      触发关闭窗口之前执行。可以调用event.preventDefault(), 阻止默认事件的触发。
  • will-quit

    • 返回 Event
      event.preventDefault(), 可以阻止默认是事件发生。
  • quit

    • 返回 Event
    • 返回 exitCode 整数
  • open-file mac

    • Event
    • String
  • open-url mac

    • Event
    • String
  • activate mac

    • Event
    • hasVisibleWindows, 布尔值类型
      当程序被激活的时候,比如第一次打开软件,比如重新打开一个再运行的软件,或者点击边栏上的图表什么的。
  • continue-activity mac

    • event Event
    • type String
    • userInfo Object

擦,好多,这货一般没啥用。

  • browser-window-blur
    • event Event
    • window BrowserWindow
      blur: 模糊
  • browser-window-focus
    • event Event
    • window BrowserWindow

获取焦点的时候,巴拉巴拉….

  • browser-window-created
    • event Event
    • window BrowserWindow

被创建的时候

  • web-contents-created

    • event Event
    • webContents WebContents
  • certificate-error

    • event Event
    • webContents WebContents
    • url String
    • error String - 错误码
    • certificate Certificate 证书
    • callback Function
      • isTrusted Boolean 证书是否被信任

    当证书验证失败的时候。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const {app} = require('electron')
    app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
    if (url === 'https://github.com') {
    // Verification logic.
    event.preventDefault()
    callback(true)
    } else {
    callback(false)
    }
    })
  • select-client-certificate

    • event Event
    • webContents WebContents
    • url URL
    • certificateList Certificate[] 证书列表
    • callback Function
    • certificate
      • Certificate 选填
        当客户端需要验证证书的时候,触发。
        1
        2
        3
        4
        5
        6
        const {app} = require('electron')
        app.on('select-client-certificate', (event, webContents, url, list, callback) => {
        event.preventDefault()
        callback(list[0])
        })
  • login 重要

    • Returns:
      • event Event
      • webContents WebContents
      • request Object
        • method String
        • url URL
        • referrer URL
      • authInfo Object
        • isProxy Boolean
        • scheme String
        • host String
        • port Integer
        • realm String
      • callback Function
        • username String
        • password String

webContents 想要做登录验证的时候。

默认是取消所有的验证,你可以重载这个方法,阻止它默认的行文(event.preventDefault),然后调用callback(username, password)去验证。

方法

  • app.quit()
  • app.exit([exitCode])
  • app.relaunch([options])

    1
    2
    3
    4
    const {app} = require('electron')
    app.relaunch({args: process.argv.slice(1).concat(['--relaunch'])})
    app.exit(0)
  • app.isReady()

  • app.focus()
  • app.hide() mac
  • app.show() mac
  • app.getAppPath(), 返回当前APP的路径
  • app.getPath(name), name: String
    返回String, 可选参数有 console.log(app.getPath('home'))
    • home 用户的家目录
    • appData 每个用户的data目录
      • %APPDATA% on Windows
      • $XDG_CONFIG_HOME or ~/.config on Linux
      • ~/Library/Application Support on macOS
    • userData, 用户的配置文件,默认是在appData目录后面加上你的app的名字
    • temp, 临时目录地址
    • exe 当前可执行文件
    • module, libchromiumcontent, 目录地址
    • desktop, 当前用户的桌面地址
    • documents, 用户的的My Documents
    • downloads, 用户的用户下载路径
    • music 用户的music地址
    • pictures 用户的图片地址
    • videos 用户的视频地址
    • pepperFlashSystemPlugin, 呃,别用了,flash的
  • app.getFileIcon(path[, options], callback)
    • path String
    • options
      • size String
        • small - 16x16
        • normal - 32x32
        • large - 48x48(Linux), 32x32(windows)
    • callback Function
      • error
      • icon
  • app.setPath(name, path)
    • name, 设置路径对应的别名
    • path,真实路径
      如果,path不存在,那么就会创建,如果报错,那么就会抛出错误。
  • app.getVersion()
  • app.getName(),当前应用的名称
  • app.setName(name)
  • app.getLocale(),获取多语言环境
  • app.addRecentDocument(path) mac*, windows**
  • app.clearRecentDocuments() mac*, windows**
  • app.makeSingleInstance(callback)

    • callback Function
      • argv String[] - 第二个这个app实例所带的参数
      • workingDirectory String - 第二个实例所在的目录地址
        设置你的app只能打开一个,
        callback,会在第二个实例启动的时候,被调用。一般这个时候,相应只是让当前的窗口获取焦点,不能被最小化。
        如果你的窗口就是主窗口,那么method返回false
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        const {app} = require('electron')
        let myWindow = null
        const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
        // 有人又点击你了,要注意啊,少年.
        if (myWindow) {
        // 所以我判断一下是不是最小化的了
        if (myWindow.isMinimized()) myWindow.restore()
        // 所以我要获取焦点
        myWindow.focus()
        }
        })
        if (shouldQuit) {
        app.quit()
        }
        // Create myWindow, load the rest of the app, etc...
        app.on('ready', () => {
        })
  • app.releaseSingleInstance(), 释放所有的单例。这样会导致多个实例,一个接一个的运行。

  • app.setUserActivity(type, userInfo[, webpageURL]) mac
  • app.getCurrentActivityType(), 获取当前的。。。 mac
  • app.setLoginItemSettings(settings[, path, args]) mac, windows
1
2
3
4
5
6
7
8
9
10
11
12
const appFolder = path.dirname(process.execPath)
const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath)
app.setLoginItemSettings({
openAtLogin: true,
path: updateExe,
args: [
'--processStart', `"${exeName}"`,
'--process-start-args', `"--hidden"`
]
})
  • app.dock.setIcon(image)mac, 设置icon图片
  • app.dock.setMenu(menu)mac, 设置dock的menu
  • app.dock.hide()mac, 隐藏dock
  • app.dock.show()mac, 显示dock
  • app.dock.getBadge()mac

BrowserWindow

创建和控制窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 在主进程里面
const {BrowserWindow} = require('electron');
// 或者在其它进程中,从renderer 进程中创建`remote`
// const {BrowserWindow} = require('electron').remote
let win = new BrowserWindow({width: 800, height: 600})
win.on('closed', () => {
win = null
})
// 加载远程页面
win.loadURL('https://github.com')
// Or 加载本地文件
win.loadURL(`file://${__dirname}/app/index.html`)

漂亮的显示窗口

  • ready-to-show事件, 加载期间会被调用,直到第一次加载成功
1
2
3
4
5
const {BrowserWindow} = require('electron')
let win = new BrowserWindow({show: false})
win.once('ready-to-show', () => {
win.show()
})
  • backgroundColor, 设置显示颜色
1
2
3
4
const {BrowserWindow} = require('electron')
let win = new BrowserWindow({backgroundColor: '#2e2c29'})
win.loadURL('https://github.com')

父窗口等

parent

1
2
3
4
5
6
const {BrowserWindow} = require('electron')
let top = new BrowserWindow()
let child = new BrowserWindow({parent: top})
child.show()
top.show()
1
2
3
4
5
6
7
8
const {BrowserWindow} = require('electron')
let child = new BrowserWindow({parent: top, modal: true, show: false})
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
child.show()
})

注意

  • mac中,modal窗口会向一个, 嗯显示效果,挺漂亮的哈
  • mac中,子窗口会与主窗口保持一个位置,而Windows和Linux中不会。

Class: BrowserWindow

new BrowserWindow([options])

  • options Object(可选)
    • width Integer, 窗口宽度,默认是 800
    • height Integer, 窗口高度, 默认是600
    • x Integer, 距离屏幕举例左边的坐标,默认是中间
    • y Integer, 距离上面的坐标,默认是中间
    • useContentSize, Boolean, width 和 height是否用于Web页面的尺寸,意味着实际的窗口大小,将包含窗口框架大小,并且稍微大一谢谢。默认是 false
    • center, Boolean, 显示在屏幕正中
    • minWidth, Integer, 最小的width,默认是0
    • minWidth Integer (optional) - Window’s minimum width. Default is 0.
    • minHeight Integer (optional) - Window’s minimum height. Default is 0.
    • maxWidth Integer (optional) - Window’s maximum width. Default is no limit.
    • maxHeight Integer (optional) - Window’s maximum height. Default is no limit.
    • resizable Boolean (optional) - 窗口是否可以调整大小. 默认是true
    • closable Boolean (optional) - 是否可以关闭窗口. Linux中不能用. 默认是 true.
    • "node-integration", 默认加载远程url的时候,是不会加载jquery等框架的,如果需要,请设置为false

Instance Events

new一个实例之后,有这些事件, close

1
2
3
4
5
6
7
8
9
window.onbeforeunload = (e) => {
console.log('I do not want to be closed')
// Unlike usual browsers that a message box will be prompted to users, returning
// a non-void value will silently cancel the close.
// It is recommended to use the dialog API to let the user confirm closing the
// application.
e.returnValue = false
}

静态方法

  • BrowserWindow.getAllWindows()
    获取所有BrowserWindows的窗口数组。
  • BrowserWindow.getFocusedWindow()
    获取当前有焦点的窗口。
  • BrowserWindow.fromWebContents(webContents)
  • BrowserWindow.fromId(id)

实例属性

1
2
3
4
const {BrowserWindow} = require('electron')
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL('https://github.com')
  • win.webContent
  • win.id

实例方法

  • win.destroy()
  • win.close()
  • win.focus()
  • win.blur()//模糊
  • win.isFocused()
  • win.isDestroyed()
  • win.show()
  • win.showInactive(), 显示窗口,但是放焦点
  • win.hide()
  • win.isVisible() , 返回Boolean值,是否用户可见
  • win.isModal(), 当前的窗口是不是modal框
  • win.maximize(), 最大化窗口
  • win.unmaximize()
  • win.restore(), 从最小化状态,重置会之前的状态
  • win.isMinimized()
  • win.setFullScreen(flag), flag: 布尔值,设置受否全屏
  • win.previewFile(path[, displayName]), Mac
  • win.closeFilePreview(), Mac
  • win.setMinimumSize(width, height)
  • win.getMinimumSize()
  • win.setMaximumSize(width, height)
  • win.getMaximumSize()
  • win.setResizable(resizable)
  • win.isMovable() Mac Window
  • win.isFullScreenable()
  • win.isAlwaysOnTop()
  • win.setTitle(title)
  • win.setSheetOffset(offsetY[, offsetX]), Mac
  • win.loadURL(url[, options])
    • url
    • options
      • httpReferrer
      • userAgent
      • extraHeaders
      • postData (UploadRawData | UploadFile | UploadFileSystem | UploadBlob)[]
1
2
3
4
5
6
7
let url = require('url').format({
protocol: 'file',
slashes: true,
pathname: require('path').join(__dirname, 'index.html')
})
win.loadURL(url)

POST:

1
2
3
4
5
6
7
win.loadURL('http://localhost:8000/post', {
postData: [{
type: 'rawData',
bytes: Buffer.from('hello=world')
}],
extraHeaders: 'Content-Type: application/x-www-form-urlencoded'
})
  • win.reload()
  • win.setMenu(menu) Linux Windows
  • win.setProgressBar(progress[, options])
    • progress Double类型

菜单

new Menu()

创建一个菜单

给项目设置菜单

1
2
3
4
5
6
7
8
9
10
const template = [
{
label: '修改',
submenu: [
{
role: 'pasteandmatchstyle'
}
]
}
]

其他页面的标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- index.html -->
<script>
const {remote} = require('electron')
const {Menu, MenuItem} = remote
const menu = new Menu()
menu.append(new MenuItem({label: 'MenuItem1', click() { console.log('item 1 clicked') }}))
menu.append(new MenuItem({type: 'separator'}))
menu.append(new MenuItem({label: 'MenuItem2', type: 'checkbox', checked: true}))
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
menu.popup(remote.getCurrentWindow())
}, false)
</script>

添加item

new MenuItem(options)

  • options Object
    • click Function (optional) - 点击时触发.
      • menuItem MenuItem
      • browserWindow BrowserWindow
      • event Event
    • role String (optional) - 定义原生操作类,有(undo, redo, cut, copy, paste, selectall, delete, minimize, reload), 这些action可以提供原生的体验.
    • type String (optional) - Can be normal, separator, submenu, checkbox or radio.
    • label String - (optional)
    • sublabel String - (optional)
    • accelerator Accelerator (optional)
    • icon (NativeImage | String) (optional)
    • enabled Boolean (optional) - 如果是 false, 置灰,并且不可点击.
    • visible Boolean (optional) - 如果是 false, 就隐藏.
    • checked Boolean (optional) - 只对checkbox 和 radio button有效.
    • submenu (MenuItemConstructorOptions[] | Menu) (optional)
    • id String (optional) - 唯一属性ID.
    • position String (optional) .

ipcMain, ipcRenderer

  • ipcMain: 主进程与子进程进行通信,
  • ipcRenderer: 子进程与主进程进行通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// main.js
const {ipcMain} = require('electron');
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg); // 'ping'
//中转一下,发给index.html
event.sender.send('asynchronous-reply', 'pong');
});
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.returnValue = 'pong'
});
1
2
3
4
5
6
7
8
9
10
// index.html.
const {ipcRenderer} = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"
ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')

webview

注意,如果需要隐藏webview,那么需要不能直接设置style="display:none", 这会导致,renderer 进程不能监控,是否加载完成等。

如果,一定要隐藏,那么请独立写css 的属性,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
webview {
display:inline-flex;
width:640px;
height:480px;
}
webview.hide {
flex: 0 1;
width: 0px;
height: 0px;
}
</style>
<!-- 隐藏 webview-->
<webview class="hide"></webview>