Electron 基础学习(2)
右键菜单
-
创建
contextMenu.js
,代码如下const { remote } = require('electron') // 右键菜单模板 // 配置参数与顶部菜单一致 const menuList = [ { label: '复制', accelerator: 'ctrl+c' }, { label: '复制', accelerator: 'ctrl+v' } ] window.addEventListener('contextmenu', function(e) { // 阻止默认事件 e.preventDefault() // 转换 let menu = remote.Menu.buildFromTemplate(menuList) // 初始化右键菜单 menu.popup({window: remote.getCurrentWindow()}) })
-
修改
index.html
,核心代码如下<html> <body> <button id="btn">点我啊</button> <div id="box"></div> <!-- 这里引入自定义的contextMenu.js --> <script src="./contextMenu.js"></script> </body> </html>
-
修改
main.js
,核心代码如下app.on('ready', () => { // 设置初始窗口 mainWindow = new BrowserWindow({ width: 600, height: 400, webPreferences: { nodeIntegration: true, contextIsolation: false, enableRemoteModule: true } }) // 设置程序初始化就打开调试窗口 mainWindow.webContents.toggleDevTools() // 加载html文件 mainWindow.loadFile('./static/html/index.html') // 设置窗口关闭事件 mainWindow.on('closed', () => { mainWindow = null }) })
-
启动后使用鼠标右键就可以看见配置好了右键菜单。
通过链接打开浏览器
打开浏览器,并访问指定链接。
-
修改
index.html
,代码如下<html> <body> <a href="www.baidu.com">百度一下</a> <!-- 这里引入下文的shell.js --> <script src="./shell.js"></script> </body> </html>
-
新建
shell.js
,代码如下const { shell } = require('electron') const link = document.querySelector('a') // 添加点击事件 link.onclick = function(e) { e.preventDefault() // 获取a的链接地址 let href = this.getAttribute('href') // openExternal、openPath两个方法好像都可以打开 shell.openExternal(href) }
-
启动之后点击
百度一下
字样,就会看到浏览器打开新的窗口访问链接地址
创建嵌套窗口
-
修改
main.js
,核心代码如下// 多引入一个BrowserView const { BrowserView } = require('electron') app.on('ready', () => { // 设置初始窗口 mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, contextIsolation: false, enableRemoteModule: true } }) // 创建BrowserView对象 let nest = new BrowserView() // 添加至主窗口上 mainWindow.setBrowserView(nest) // 设置属性 nest.setBounds({ x: 0, y: 120, width: 1200, height: 600 }) // 添加嵌套地址,也可以使用loadFile加载本地html nest.webContents.loadURL('https://www.baidu.com') // 设置程序初始化就打开调试窗口 mainWindow.webContents.toggleDevTools() // 加载html文件 mainWindow.loadFile('./static/html/index.html') // 设置窗口关闭事件 mainWindow.on('closed', () => { mainWindow = null }) })
-
启动就能看见了
打开子窗口
使用window.open()
方法,浏览器也有这个方法
-
修改
shell.js
,核心代码如下link.onclick = function(e) { e.preventDefault() // 获取a的链接地址 let href = this.getAttribute('href') // 可以打开网络地址,也可以打开本地地址 // 需要注意的是,路径是相对于引入shell.js的html文件的路径 window.open(href) }
-
启动程序点击链接就可以打开新窗口了!
子、父窗口之间的通信
使用window.openr.postMessage()
-
window.openr.postMessage(message, targetOrigin, [transfer])
message
:将要发送到其他window
的数据;targetOrigin
:目标源,可以限定只接收来自某个URL下的数据,也可以是*
或空(不限制)transfer
:(可选)是一串和message同时传递的Transferable对象
-
修改
remote.html
(上文使用remote.BrowserWindow
打开的html页面)<html> <body> <p>这里是子窗口</p> <button>点击发送消息</button> </body> <script> let btn = document.querySelector('button') btn.onclick = function(e) { window.opener.postMessage('这是一条发给父页面的消息', '*') } </script> </html>
-
修改
shell.js
(当前index.html
引入的js
文件),添加如下代码window.addEventListener('message', (e) => { // 这里就可以看到传递过来的信息对象 console.log(e) })
该对象包括:
data:来自其他window的数据。
origin:调用postMessage的窗口url。
source:发送消息窗口的引用。可以使用该方法使来自不同源的窗口进行双向通信。
-
启动程序,在开启控制台的状态下,点击子窗口的按钮就能看到输出了!
选择文件对话框
虽然可以使用input
完成,但是还是推荐使用electron
的方法。主要使用dialog
模块。
-
修改
index.html
<html> <body> <button> 点击选择图片 </button> <img width="100%" /> <script src="./shell.js"></script> </body> </html>
-
修改
shell.js
// 如果是在主进程上使用 是 const { dialog } = require('electron') // 而这边是在渲染进程上使用 const { dialog } = require('electron').remote const btn = document.querySelector('button') const img = document.querySelector('img') btn.onclick = function (){ dialog.showOpenDialog({ title: '请选择你要选择的图片', // 过滤文件类型 filters: [ { name: 'jpg', // 可选类型数组 extensions: ['jpg'] } ], // 选择按钮文本 buttonLabel: '选择图片' }).then(({canceled, filePaths}) => { // canceled:是否点击取消 // filePaths: 文件路径数组 if (canceled) { window.alert('您已取消选择。') } else { img.setAttribute('src', filePaths[0]) } }).catch(err => { console.log(err) }) } }
保存文件对话框
使用的也是dialog
模块,上文有官方文档
-
修改
index.html
<html> <body> <button id="watchBtn">查看图片</button> <button id="saveBtn">保存文本</button> <img alt="图片展示" width="100%" /> <script src="./shell.js"></script> </body> </html>
-
修改
shell.js
const { dialog } = require('electron').remote const fs = require('fs') // DOM元素 const watchBtn = document.querySelector('#watchBtn') const saveBtn = document.querySelector('#saveBtn') const img = document.querySelector('img') // 测试数据 const text = `<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>新的未来</title> </head> <body> <button id="watchBtn">查看图片</button> <button id="saveBtn">保存图片</button> <img alt="图片展示" width="100%" /> <script src="./shell.js"></script> </body> </html> ` watchBtn.onclick = function(e) { dialog.showOpenDialog({ title: '请选择你要选择的图片', filters: [ { name: 'jpg', extensions: ['jpg'] } ], buttonLabel: '选择图片' }).then(({canceled, filePaths}) => { if (canceled) { window.alert('您已取消选择。') } else { img.setAttribute('src', filePaths[0]) } }).catch(err => { console.log(err) }) } saveBtn.onclick = function(e) { dialog.showSaveDialog({ title: '请选择你要保存的内容', buttonLabel: '选择', // 设置可保存的文件类型 filters: [ { name: 'Img', extensions: ['jpg', 'png'] }, { name: 'Text', extensions: ['txt', 'md'] }, { name: 'Code', extensions: ['js', 'html', 'css', 'ts', 'java', 'json'] } ] }).then(({canceled, filePath}) => { if (!canceled) { // 也可以使用同步保存 fs.writeFile(filePath, text, err => { if (err) { throw err } else { // 提示 dialog.showMessageBox({ title: '操作提示', message: '保存成功', type: 'none' }) } }) } }).catch(err => { console.log(err) }) } window.addEventListener('message', (e) => { console.log(e) })
消息提示框
使用dialog.showMessageBox
,具体api
可以查看上文链接
-
使用方式如下:
// 如果是位于主进程,使用 require('electron') // 如果是渲染进程,使用 require('electron').remote const { dialog } = require('electron').remote dialog.showMessageBox({ title: '提示框', // icon类型 type: 'info', // 提示文本 message: '这是一段测试文本', // 设置按钮选项 // 需要注意的是,按下后返回是文本对应的下标,需自己做好处理 buttons: ['确定', '取消'] }).then(({response, checkboxChecked}) => { // response 按钮对应buttons下标 // checkboxChecked 如果设置了 checkboxLabel,返回复选框是否被选中的状态。 // 之后就可以做一些事情了 }).catch(err => { console.log(err) })
监听断网、联网事件
使用的是js
原生事件,记录下来
// online 连接上网络,启动时本身是联网状态是不会触发的
window.addEventListener('online', () => {
alert('Online')
})
// offline 断开网络
window.addEventListener('offline', () => {
alert('offline')
})
发送通知
使用的是Notification
模块。分两种情况,渲染进程可以很方便的使用HTML的Notification
,而主进程需要引入Notification
模块
-
渲染进程
<html> <body> <button id="btn">发送通知</button> </body> <script> const btn = document.getElementById('btn') btn.onclick = () => { let option = { title: '提示框', body: '这是提示信息!' } // 第一个参数是title: String // 第二个参数是包含提示信息的对象: {body: 'xxx'} new Notifiaction(option.title, option) } </script> </html>
-
主进程
const { Notifiaction } = require('electron') function showNotifiaction(body) { let option = { title: '提示', body } new Notifiaction(option).show() } app.on('reedy', () => { // 加入这一句 showNotifiaction('提示信息') })
注册全局快捷键
使用globalShortcut
模块
const { globalShortcut } = require('electron')
app.on('ready', () => {
// 添加快捷键
globalShortcut.register('ctrl+q', () => {
console.log('按下了 ctrl + q')
})
// 多个快捷键绑定一个事件
globalShortcut.registerAll(['ctrl+q', 'ctrl+w'], () => {
console.log('按下了 啥我也不太清楚啊')
})
// 有时,快捷键会冲突,需要判断快捷键是否添加
let isRegister = globalShortcut.isRegistered('ctrl+q') ? 'True' : 'False'
// 有时我们需要取消快捷键的绑定
// 参数为绑定的快捷键
globalShortcur.unrgister('ctrl+q')
// 当然也可以注销所有快捷键
globalShortcur.unrgisterAll()
})
// 主进程退出前触发事件
app.on('will-quit', () => {
// 可以在这里注销快捷键
})
复制到剪切板
使用的是clipboard
模块,在渲染、主进程都可以使用,官方文档
<html>
<body>
复制文本:<span id="tip">使用的是`clipboard`模块,在渲染、主进程都可以使用</span>
<button id="btn">发送通知</button>
</body>
<script>
const { clipboard } = require('electron')
const btn = document.getElementById('btn')
const tip = document.getElementById('tip')
// 复制文本
btn.onclick = () => {
clipboard.writeText(tip.innerHTML)
}
</script>
</html>
总结
到这里我就将Electron
的基础内容学完了,其实最主要的是理解其主线程和渲染进程,其他的API
在需要的时候查阅文档即可。