目录
7.dialog
1.app
控制应用程序的事件生命周期
事件:
'ready' 当 Electron 完成初始化时,发出一次
'window-all-closed' 当所有的窗口都被关闭时触发
'before-quit' 在程序关闭窗口前发信号
'will-quit' 当所有窗口被关闭后触发,同时应用程序将退出
'quit' 在应用程序退出时发出
open-file macOS 当用户想要在应用中打开一个文件时发出
open-url macOS 当用户想要在应用中打开一个 URL 时发出open-url
activate macOS 当应用被激活时发出
did-become-active macOS 当应用被激活时发出
login 当 webContents
要进行基本身份验证时触发
render-process-gone 渲染器进程意外消失时触发。 这种情况通常因为进程崩溃或被杀死
child-process-gone 子进程意外消失时触发。 这种情况通常因为进程崩溃或被杀死。 子进程不包括渲染器进程
session-created 当 Electron创建了一个新的 session
后被触发
方法
app.quit()
尝试关闭所有窗口,将首先发出 before-quit
事件。 如果所有窗口都已成功关闭, 则将发出 will-quit
事件, 并且默认情况下应用程序将终止。
app.exit([exitCode])
使用 exitCode
立即退出
app.reluanch([options])
app.isReady() 是否完成初始化
app.whenReady() 当完成初始化
app.getPath(name)获取当前文件的路径
app.getFileIcon(path[, options])
读取文件的关联图标
app.getVersion()
用程序的版本号
app.getName()
当前应用程序的名称
app.setName(name)
设置当前应用程序的名字
app.getLocale()
应用程序区域语言
app.addRecentDocument(path)
将此 path
添加到最近打开的文件列表中
app.clearRecentDocuments()
清空最近打开的文档列表
2.BrowserWindow
创建并控制浏览器窗口,在 app
模块 emitted ready
事件之前,不能使用此模块
通过使用 parent
选项,可以创建子窗口 parent: mainWindow
模态窗口,模态窗口是禁用父窗口的子窗口,创建模态窗口必须设置 parent
和 modal
选项,父窗口会显示但不能操作,子窗口关闭了才能操作
父子窗口通信:
子窗口向父窗口传递信息
window.opener.postMessage('test');
父窗口添加监听
window.addEventListener()
3.BrowserView
创建和控制视图
BrowserView
被用来让BrowserWindow嵌入更多的 web 内容。 它就像一个子窗口,除了它的位置是相对于父窗口
const mainWindow = new BrowserWindow({ width: 800, height: 600 })
const view = new BrowserView()
mainWindow.setBrowserView(view)
view.setBounds({ x: 0, y: 0, width: 300, height: 300 })
view.webContents.loadURL('https://www.baidu.com')
setBounds
调整视图的大小,并将它移动到窗口边界
4.Menu
桌面应用程序有两种类型的菜单 – application menu (在顶部栏上)和context menu (右键菜单)
Menu 和MenuItem 模块仅在主进程中可用。 要在渲染器过程中使用这些模块,需要remote 模块
Menu.setApplicationMenu(menu) 设置菜单
Menu.buildFromTemplate(template) template
是一个options
类型的数组,用于构建MenuItem
创建原生菜单
let menuTemplate = [ {
label:"文件",
submenu:[
// accelerator 配置快捷键
{label:'新建',accelerator:"ctrl+n",click:()=>{console.log("BUILD")}},
{label:'打开',accelerator:"ctrl+o",click:()=>{console.log("NEW")}},
{type:"separator"},
{label:'保存',accelerator:"ctrl+s",click:()=>{console.log("SAVE")}}
]
},
{
label:"编辑",
submenu:[
// role按角色进行配置
{label:"复制",role:"copy",click:()=>{console.log("复制文件")}},
{label:"粘贴",role:"paste",click:()=>{console.log("粘贴文件")}}
]
}
]
let menuBuilder = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menuBuilder);
效果:
label : 菜单名字 submenu: 子菜单项 click: 点击事触发 type: ‘separator’ 分隔条
menu.popup([options])
弹出此菜单作为上下文菜单
上下文弹出菜单
5.Tray
将图标和上下文菜单添加到系统通知
const { app, Menu, Tray } = require('electron')
let tray = null
app.whenReady().then(() => {
tray = new Tray('./files/icon/flutter_logo_color.png')
const contextMenu = Menu.buildFromTemplate([
{ label: 'Item1',click:()=>{console.log("Item1")}},
{ label: 'Item2',click:()=>{console.log("Item2")} },
{ label: 'Item3',click:()=>{console.log("Item3")} },
{ label: 'Item4', click:()=>{console.log("Item4")} }
])
tray.setToolTip('This is my application.')
tray.setContextMenu(contextMenu)
tray.on('click',()=>{
console.log("click")
})
})
tray.setToolTip(toolTip)
设置鼠标指针在托盘图标上悬停时显示的文本
tray.destroy()
立即销毁该任务栏图标
tray.setImage(image)
设置image
作为托盘中显示的图标
tray.setContextMenu(menu)
设置这个图标的内容菜单
tray.isDestroyed()
判断托盘图标是否被销毁
tray是基于事件 可以监听
click事件 当该图标被点击时触发
right-click 当该图标被右击时触发
double-click 当该图标被双击时触发
mouse-move 当鼠标在该任务栏图标上移动时触发
6.Notification
创建OS(操作系统)桌面通知,主进程通知,如果要显示来自渲染进程的通知, 应该使用 HTML5 Notification API
主进程通知
function creatNotification () {
const isAllowed = Notification.isSupported();
if (isAllowed) {
const options = {
title: '标题',
body: '正文文本,显示在标题下方',
silent: true, // 系统默认的通知声音
icon: '', // 通知图标
}
const notification = new Notification(options);
notification.on('click', () => { console.log('click'); });
notification.on('show', () => { console.log('show'); });
notification.on('close', () => { console.log('close'); });
notification.show();
}
}
Notification.isSupported()
当前系统是否支持桌面通知
new Notification([options]) 创建通知
show() 显示通知
事件 show 当通知显示时触发
click 当通知被点击时触发
close当通知被关闭时触发
渲染进程通知
1. 安装 cnpm install --save node-notifier
2.
const notifier = require('node-notifier')
const path = require('path');
notifier.notify ({
title: 'My awesome title',
message: 'Hello from electron, Mr. User!',
icon: path.join('','/home/ayushgp/Desktop/images.png'), // Absolute path
}, function (err, response) {
// Response is response from notification
});
notifier.on('click', function (notifierObject, options) {
console.log("You clicked on the notification")
});
notifier.on('timeout', function (notifierObject, options) {
console.log("Notification timed out!")
});
7.dialog
主进程:用户与程序交互的对话框
dialog.showOpenDialog({title: '保存位置',
defaultPath: 'E:\\alog\\src',
properties: ['openDirectory', 'multiSelections'] }).then((fileResult)=>{
console.log('openDirectory',fileResult)
})
1. dialog.showOpenDialogSync([browserWindow, ]options)
browserWindow
BrowserWindow (可选)选项
对象title
string (可选) - 对话框窗口的标题defaultPath
string (可选) - 对话框的默认展示路径buttonLabel
string (可选) - 「确认」按钮的自定义标签, 当为空时, 将使用默认标签。filters
FileFilter[] (可选)properties
string[] (可选) - 包含对话框相关属性。 支持以下属性值:openFile
- 允许选择文件openDirectory
- 允许选择文件夹multiSelections
-允许多选。showHiddenFiles
-显示对话框中的隐藏文件。
返回 string[] | undefined
, 用户选择的文件路径,如果对话框被取消了 ,则返回undefined
。
browserWindow
参数允许该对话框将自身附加到父窗口, 作为父窗口的模态框。
filters
指定一个文件类型数组,用于规定用户可见或可选的特定类型范围。 例如:
{
filters: [
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
{ name: 'Custom File Type', extensions: ['as'] },
{ name: 'All Files', extensions: ['*'] }
]
}
2. dialog.showOpenDialog([browserWindow, ]options)
返回 Promise<Object>
- resolve包含以下内容的object:
canceled
boolean - 对话框是否被取消。filePaths
string[] - 用户选择的文件路径的数组. 如果对话框被取消,这将是一个空的数组。
其他与showOpenDialogSync相同,区别是showOpenDialog是异步的,showOpenDialogSync是同步的
3.dialog.showSaveDialogSync([browserWindow, ]options)
browserWindow
BrowserWindow (可选)选项
对象title
string (可选) - 对话框标题。 无法在一些 Linux 桌面环境中显示。defaultPath
string (可选) - 默认情况下使用的绝对目录路径、绝对文件路径或文件名。buttonLabel
string (可选) - 「确认」按钮的自定义标签, 当为空时, 将使用默认标签。filters
FileFilter[] (可选)properties
string[] (可选)showHiddenFiles
-显示对话框中的隐藏文件。
返回 string | undefined
, 用户选择的文件路径,如果对话框被取消了 ,则返回undefined
。
同步保存文件内容
4. dialog.showSaveDialog([browserWindow, ]options)
返回 Promise<Object>
- resolve包含以下内容的object:
canceled
boolean - 对话框是否被取消。filePath
string (可选) - 如果对话框被取消,该值为undefined
。
异步保存文件内容
dialog.showSaveDialog({title: '保存位置',
defaultPath: 'E:\\alog\\src',
properties: ['openDirectory', 'multiSelections'] }).then((fileResult) => {
console.log('openDirectory',fileResult)
fs.writeFileSync(fileResult.filePath, "文件保存的内容");
})
5. dialog.showMessageBoxSync([browserWindow, ]options)
browserWindow
BrowserWindow (可选)选项
对象message
string - message box 的内容.type
string (可选) - 可以为"none"
,"info"
,"error"
,"question"
或者"warning"
. 在 Windows 上,"question"
与"info"
显示相同的图标, 除非你使用了"icon"
选项设置图标。 在 macOS 上,"warning"
和"error"
显示相同的警告图标buttons
string[] (可选) - 按钮文本数组。 在 Windows上,一个空数组将导致按钮被标为“OK”。defaultId
Integer (可选) - 在 message box 对话框打开的时候,设置默认选中的按钮,值为在 buttons 数组中的索引.title
string (可选) - message box 的标题,一些平台不显示.detail
string (可选) - 额外信息.icon
(NativeImage | string) (可选)cancelId
Integer (可选) - 用于取消对话框的按钮的索引,例如Esc
键. 默认情况下,它被分配给第一个按钮,文字为 “cancel” 或 “no”。 如果不存在这个标签的按钮,同时该选项又未设置,返回值为0
。noLink
boolean (可选) - 在Windows上,应用将尝试找出哪个buttons
是常用按钮(例如 "Cancel" 或 "Yes"),然后在对话框中以链接命令的方式展现其它的按钮。 这可以使对话框以现代Windows应用程序的风格显示。 如果你不喜欢这个行为, 你可以设置noLink
为true
.normalizeAccessKeys
boolean (可选) -规范跨平台的键盘访问键。 默认值为false
. 用&
连接和转换键盘访问键, 以便它们在每个平台上正常工作.&
字符会在macOS上被删除,在 Linux 上会被转换为_
,在 Windows 上保持不变。 例如Vie&w
的按钮标签在 Linux 上会被转换为Vie_w
,在 macOS 转换为View
并且可以被选择。而Windows和Linux上表示Alt-W
。
返回 Integer
- 点击的按钮的索引。
显示一个消息框,它将阻塞进程直到消息框关闭。 它返回点击的按钮的索引。
browserWindow
参数允许该对话框将自身附加到父窗口, 作为父窗口的模态框。 如果 浏览器窗口
没有显示,则对话框不会附属于它。 在这种情况想,它将作为一个独立的窗口显示。
6. dialog.showMessageBox([browserWindow, ]options)
返回 Promise<Object>
- resolve包含以下属性的promise:
response
number - 点击的按钮的索引。checkboxChecked
boolean - 如果设置了checkboxLabel
,返回复选框是否被选中的状态。 否则,返回false
。
dialog.showMessageBox({
title: '提示',
message: '确定要XXX吗?',
type: 'question',
buttons: ['确定', '取消'],
defaultId: 0,
}).then((MessageResult)=>{
console.log('showMessageBox', MessageResult)
})
返回例子:showMessageBox { response: 0, checkboxChecked: false }
7. dialog.showErrorBox(title, content)
title
string - 显示在错误框中的标题.content
string - 显示在错误框中的文本内容.
显示一个显示错误消息的模态对话框。
渲染进程弹出对话框需要异步通信,渲染进程给主线程发送消息,主进程收到消息 弹出对话框
8.主进程与渲染进程的通信
1.主进程概念
package.json中指定的main是主进程,在主进程中直接引入的js文件也是主进程(如:require(’./mainProcess/menu.js’))
2.渲染进程概念
在html文件中引入的js文件属于渲染进程
例如:index.html文件中引入的index.js就属于渲染进程
通信方式1:ipc
IPC 通信包含主进程的 ipcMain 对象和渲染进程的 ipcRenderer 对象。因为是通信,所以主进程和渲染进程都必须有接收和发送这两个功能:
- 主进程
- 发送:window.webContents.send(channel_name, data)
- 接收:ipcMain.on/handle(channel_name, callback)
- 渲染进程
- 发送:ipcRenderer.send/invoke(channel_name, data)
- 接收:ipcRenderer.on(channel_name, callback)
渲染进程--->主进程异步消息
//渲染进程
ipcRenderer.send('channal', 'renderer message')
ipcRenderer.on('channal2', (event,arg) => {
console.log('renderer get', arg);
})
//主进程
ipcMain.on('channal', (event, arg) => {
console.log('Main get ',arg);
event.reply('channal2', 'main message')
})
渲染进程--->主进程 同步消息
//渲染进程同步消息
const mainMessage = ipcRenderer.sendSync('channal', 'renderer message')
console.log('renderer get', mainMessage);
//主进程
ipcMain.on('channal', (event, arg) => {
console.log('Main get ',arg);
event.returnValue = 'main message'
})
渲染进程--->主进程 结合Promise (推荐使用)
//渲染进程
ipcRenderer.invoke('channal', 'renderer message').then( (message) => {
console.log('renderer get', message);
})
//主进程
ipcMain.handle('channal', (event, arg) => {
console.log('Main get ',arg);
return 'send main message'
})
通信方式2:MessageChannel
//渲染进程
ipcRenderer.on("port", (e) => {
e.ports[0].onmessage = (messageEvent) => {
console.log('收到的', messageEvent.data.some);
};
});
//主进程
const { port1, port2 } = new MessageChannelMain();
mainWindow.webContents.postMessage("port", null, [port2]);
port1.postMessage({ some: "传递消息" });
setTimeout(()=>{
port1.postMessage({ some: "传递消息2" });
},5000)
MessagePortMain 主进程中用于通道消息传递的端口接口
9.预加载脚本(preload)
preload 只能运行在渲染脚本中,可以访问node
用法:1.创建BrowserWindow时,指定加载脚本路径
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true,
sandbox: false,
webSecurity: false,
preload: path.join(__dirname, './tools/preload.js'),
contextIsolation: false
}
})
2. 脚本内容
console.log('这是预加载脚本');
window.test = function() {
console.log('这是预加载脚本function')
}
window.updataApp = function updataApp() {
console.log('App自动更新')
}
3. 在渲染进程js里面直接使用
test()
updataApp()
10.session
管理浏览器会话、cookie、缓存、代理设置等
获取session方式
const { session } = require('electron')
let ses = session.defaultSession
还可以这样获取
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
const ses = win.webContents.session
这两种方式获取的是相等的
session.fromPartition(partition[, options])
返回一个session.根据partition设置的字符串,产生一个session.
当这里已存在一个Session
具有相同的partition
, 它将被返回; 否则一个新的Session
实例将根据options
被创建。
如果 partition
以 persist:
开头, 该页面将使用持续的 session,并在所有页面生效,且使用同一个partition
. 如果没有 persist:
前缀, 页面将使用 in-memory session. 如果没有设置partition
,app 将返回默认的session。
ses.setUserAgent(userAgent[, acceptLanguages])
ses.getUserAgent()
ses.setSSLConfig(config)
ses.cookies 获取cookies
ses.webRequest 获取webRequest
11.cookies
从ses获取cookies
const { session } = require('electron')
// 查询所有 cookies。
session.defaultSession.cookies.get({})
.then((cookies) => {
console.log(cookies)
}).catch((error) => {
console.log(error)
})
// 查询所有与设置的 URL 相关的所有 cookies.
session.defaultSession.cookies.get({ url: 'http://www.github.com' })
.then((cookies) => {
console.log(cookies)
}).catch((error) => {
console.log(error)
})
// 设置一个 cookie,使用设置的名称;
// 如果存在,则会覆盖原先 cookie.
const cookie = { url: 'http://www.github.com', name: 'dummy_name', value: 'dummy' }
session.defaultSession.cookies.set(cookie)
.then(() => {
// success
}, (error) => {
console.error(error)
})
设置一个cookie
ses.cookies.set({ url: 'http://dev.luluhero.com', name:'ci_session2', value: 'ssl660gvrg3fko8coj7mqkh2sn46t3bi'})
如果url已经存在相同name的cookie会设置不成功
12.webRequest
从ses获取webRequest
webRequest.onBeforeRequest([filter, ]listener)
当请求即将发生时,调用listener(details, callback)
。
const filter = {
urls: ['https://www.hao123.com/', 'http://www.baidu.com/']
}
session.defaultSession.webRequest.onBeforeRequest(filter, (details, callback) => {
console.log('details', details);
callback({ redirectURL: 'https://www.sina.com.cn/' })
})
mainWindow.loadURL('http://www.baidu.com/')
请求百度时,重定向到新浪
filter:指定的地址
details:请求的详情
redirectURL:重定向的URL
webRequest.onBeforeSendHeaders([filter, ]listener)
请求之前修改请求头
const filter = {
urls: ['https://www.hao123.com/*', '*://*.baidu.com/*']
}
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
console.log('details', details.requestHeaders);
details.requestHeaders['Cookie'] = 'ASSSS=8F806A509ED37E752B5787D6E2073D9B'
details.requestHeaders['User-Agent'] = 'MyAgent'
callback({ requestHeaders: details.requestHeaders })
})
mainWindow.loadURL('http://www.baidu.com/')
可以看到cookie和User-Agent都改了
webRequest.onHeadersReceived([filter, ]listener)
当HTTP请求接收到响应头后,会通过调用 listener(details, callback)
方法来触发listener
webRequest.onResponseStarted([filter, ]listener)
当收到响应体的第一个字节时, 将以 listener(details)
的形式来调用 listener
webRequest.onBeforeRedirect([filter, ]listener)
当服务器的初始重定向即将发生时,将以 listener(details)
的方式调用listener
webRequest.onCompleted([filter, ]listener)
当请求完成时,将以 listener(details)
的方式调用listener
webRequest.onErrorOccurred([filter, ]listener)
当发生错误时,将以 listener(details)
的方式调用listener
13.
Debugger
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
try {
win.webContents.debugger.attach('1.1')
} catch (err) {
console.log('Debugger attach failed : ', err)
}
win.webContents.debugger.on('detach', (event, reason) => {
console.log('Debugger detached due to : ', reason)
})
win.webContents.debugger.on('message', (event, method, params) => {
if (method === 'Network.requestWillBeSent') {
if (params.request.url === 'https://www.github.com') {
win.webContents.debugger.detach()
}
}
})
win.webContents.debugger.sendCommand('Network.enable')
attach 选择调试版本
sendCommand 设置调试内容
on('message') 响应调试内容
on('detach') 关闭调试的响应
detach() 关闭调试