1042 lines
23 KiB
Markdown
1042 lines
23 KiB
Markdown
# Electron 入门
|
||
|
||
> WARNING: 文章部分内容已经过时,仅适用于 Electron ^11.2.1
|
||
|
||
## 技术架构
|
||
|
||
Electron = Chromium + Node.js + Native APIs
|
||
|
||
## 工作流程
|
||
|
||
启动APP -> 主进程创建window -> win加载界面 -> xxx行为
|
||
|
||
### 主进程
|
||
|
||
- 只有主进程才可以进行GUI的API操作
|
||
- 只有一个
|
||
|
||
### 渲染进程
|
||
|
||
- 可以有多个
|
||
- 和主进程通信完成原生API操作
|
||
|
||
## 环境搭建
|
||
|
||
1. 使用官方 Quick Start
|
||
|
||
```bash
|
||
$ git clone https://github.com/electron/electron-quick-start
|
||
$ cd electron-quick-start
|
||
$ npm install
|
||
```
|
||
|
||
```javascript
|
||
// 01 创建一个窗口
|
||
// 02 让窗口加载了一个界面,这个界面就是用Web技术实现, 运行在渲染进程
|
||
function createWindow () {
|
||
// Create the browser window.
|
||
const mainWindow = new BrowserWindow({
|
||
width: 800,
|
||
height: 600,
|
||
webPreferences: {
|
||
preload: path.join(__dirname, 'preload.js')
|
||
}
|
||
})
|
||
|
||
// and load the index.html of the app.
|
||
mainWindow.loadFile('index.html')
|
||
|
||
// Open the DevTools.
|
||
// mainWindow.webContents.openDevTools()
|
||
// ...
|
||
}
|
||
```
|
||
|
||
2. 手动创建项目
|
||
|
||
```javascript
|
||
// main.js
|
||
const {app, BrowserWindow} = require('electron') // 导包
|
||
|
||
// 当 app 启动之后执行窗口创建等操作
|
||
app.whenReady().then(() => {
|
||
const mainWin = new BrowserWindow({
|
||
width: 600,
|
||
height: 400
|
||
})
|
||
|
||
// 在当前窗口中加载指定界面让它显示具体的内容
|
||
mainWin.loadFile('index.html')
|
||
|
||
mainWin.on('close', () => {
|
||
// ...
|
||
})
|
||
})
|
||
|
||
app.on('window-all-closed', () => {
|
||
// ...
|
||
app.quit()
|
||
})
|
||
```
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<!doctype html>
|
||
<head>
|
||
<title>这个窗口标题</title>
|
||
</head>
|
||
|
||
<body>
|
||
<h1>嘿!这是一段文字!</h1>
|
||
</body>
|
||
```
|
||
|
||
```json
|
||
// package.json
|
||
{
|
||
"name": "xxxx", // 项目的名字
|
||
"version": "x.x.x", // 项目的版本
|
||
"description": "", // 描述
|
||
"main": "main.js", // 入口文件
|
||
"scripts": {
|
||
"start": "electron ." // npm start
|
||
},
|
||
"keywords": [], // 关键词?
|
||
"author": "", // 作者
|
||
"license": "ISC", // 协议
|
||
"devDependencies": {
|
||
"electron": "^11.2.1" // 开发依赖
|
||
}
|
||
}
|
||
|
||
```
|
||
|
||
## 生命周期
|
||
|
||
ready: app初始化完成
|
||
|
||
dom-ready: 一个窗口中的文本加载完成
|
||
|
||
did-finsh-load: 导航完成时出发
|
||
|
||
window-all-closed: 所有窗口都被关闭时触发
|
||
|
||
before-quit: 在关闭窗口之前触发
|
||
|
||
will-quit: 在窗口关闭并且应用退出时触发
|
||
|
||
quit: 当所有窗口被关闭时触发
|
||
|
||
closed: 当窗口关闭时触发,此时删除窗口引用
|
||
|
||
```javascript
|
||
const { app, BrowserWindow } = require('electron')
|
||
|
||
function createWindow() {
|
||
let mainWin = new BrowserWindow({
|
||
width: 600,
|
||
height: 400
|
||
})
|
||
|
||
mainWin.loadFile('index.html')
|
||
|
||
mainWin.webContents.on('did-finish-load', () => {
|
||
console.log('3 - did finish load')
|
||
})
|
||
|
||
mainWin.webContents.on('dom-ready', () => {
|
||
console.log('2 - dom ready')
|
||
})
|
||
|
||
mainWin.on('close', () => {
|
||
console.log('8 - win closed') // 多窗口时最后触发
|
||
mainWin = null // 删除引用,释放空间
|
||
})
|
||
}
|
||
|
||
app.on('ready', () => {
|
||
console.log('1 - ready')
|
||
createWindow()
|
||
})
|
||
|
||
app.on('window-all-closed', () => {
|
||
console.log('4 - window all closed')
|
||
app.quit()
|
||
})
|
||
|
||
app.on('before-quit', () => {
|
||
console.log('5 - before quit')
|
||
})
|
||
|
||
app.on('will-quit', () => {
|
||
console.log('6 - will-quit')
|
||
})
|
||
|
||
app.on('quit', () => {
|
||
console.log('7 - quit')
|
||
})
|
||
|
||
```
|
||
|
||
## 窗口大小
|
||
|
||
```javascript
|
||
function createWindow() {
|
||
let mainWin = new BrowserWindow({
|
||
x: 100, // 相对于屏幕左上角
|
||
y: 100,
|
||
show: false, // 防止首页白屏
|
||
width: 800,
|
||
height: 400,
|
||
maxHeight: 600, // 最大值
|
||
maxWidth: 1000,
|
||
minHeight: 200, // 最小值
|
||
minWidth: 300,
|
||
resizable: false // 固定大小,禁止缩放
|
||
})
|
||
|
||
// 防止首页白屏,否则不显示
|
||
mainWin.on('ready-to-show', () => {
|
||
mainWin.show()
|
||
})
|
||
|
||
// ...
|
||
}
|
||
```
|
||
|
||
## 窗口标题及环境
|
||
|
||
```javascript
|
||
// main.js
|
||
function createWindow() {
|
||
let mainWin = new BrowserWindow({
|
||
width: 800,
|
||
height: 600,
|
||
show: false,
|
||
title: "标题", // 要在网页里的标题去除
|
||
icon: "w.png", // 设置图标
|
||
frame: true, // 是否显示标题栏
|
||
transparent: false, // 透明窗体
|
||
autoHideMenuBar: true, // 隐藏菜单
|
||
webPreferences: {
|
||
nodeIntegration: true, // Node集成环境
|
||
enableRemoteModule: true, // 开启远程模块 remote
|
||
}
|
||
})
|
||
|
||
// ...
|
||
}
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
const { remote } = require('electron')
|
||
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
// 点击按钮打开新窗口
|
||
const oBtn = document.getElementById('btn')
|
||
oBtn.addEventListener('click', () => {
|
||
// 创建窗口
|
||
let indexMain = new remote.BrowserWindow({
|
||
width: 200,
|
||
height: 200
|
||
})
|
||
|
||
indexMain.loadFile('list.html')
|
||
|
||
indexMain.on('close', () => {
|
||
indexMain = null
|
||
})
|
||
})
|
||
})
|
||
```
|
||
|
||
## 自定义窗口的实现
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Document</title>
|
||
<style>
|
||
/* ... */
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="menu-container">
|
||
<div class="left">
|
||
<div class="logo"></div>
|
||
<div class="title">Electron 自定义标题栏</div>
|
||
</div>
|
||
<div class="right">
|
||
<div class="function min">
|
||
<!-- ... -->
|
||
</div>
|
||
<div class="function max">
|
||
<!-- ... -->
|
||
</div>
|
||
<div class="function close">
|
||
<!-- ... -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="app">
|
||
<h2>主体内容</h2>
|
||
</div>
|
||
|
||
<script src="index.js"></script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
const { remote } = require('electron')
|
||
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
// 利用 remote 获取当前窗口对象
|
||
let mainWin = remote.getCurrentWindow()
|
||
|
||
// 获取元素添加点击操作的监听
|
||
let aBtns = document.getElementsByClassName('function')
|
||
|
||
aBtns[0].addEventListener('click', () => {
|
||
// 最小化
|
||
mainWin.minimize()
|
||
})
|
||
|
||
aBtns[1].addEventListener('click', () => {
|
||
// 最大化
|
||
mainWin.isMaximized() ? mainWin.restore() : mainWin.maximize()
|
||
})
|
||
|
||
aBtns[2].addEventListener('click', () => {
|
||
// 关闭窗口操作
|
||
mainWin.close()
|
||
})
|
||
})
|
||
```
|
||
|
||
## 阻止窗口关闭
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<html lang="en">
|
||
<head>
|
||
<!-- ... -->
|
||
</head>
|
||
<body>
|
||
<!-- ... -->
|
||
<div class="dialog">
|
||
<div class="message">
|
||
是否关闭?
|
||
</div>
|
||
<span class="confirm yes">是</span>
|
||
<span class="confirm no">否</span>
|
||
</div>
|
||
|
||
<script src="index.js"></script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
const { remote } = require('electron')
|
||
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
|
||
window.onbeforeunload = function () {
|
||
let oBox = document.getElementsByClassName('dialog')[0]
|
||
oBox.style.display = 'block'
|
||
|
||
let yBtn = oBox.getElementsByClassName('confirm')[0]
|
||
let nBtn = oBox.getElementsByClassName('confirm')[1]
|
||
|
||
yBtn.addEventListener('click', () => {
|
||
mainWin.destroy() // 不用 close 防止死循环
|
||
})
|
||
|
||
nBtn.addEventListener('click', () => {
|
||
oBox.style.display = 'none'
|
||
})
|
||
|
||
return false
|
||
}
|
||
|
||
// ...
|
||
}
|
||
```
|
||
|
||
## 父子及模态窗口
|
||
|
||
```javascript
|
||
// index.js
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
let oBtn = document.getElementById('btn')
|
||
oBtn.addEventListener('click', () => {
|
||
let subWin = new remote.BrowserWindow({
|
||
// ...
|
||
parent: remote.getCurrentWindow(), // 设置父窗口
|
||
modal: true, // 设置模态窗口
|
||
})
|
||
// ...
|
||
})
|
||
})
|
||
```
|
||
|
||
## 自定义菜单
|
||
|
||
[Electorn文档 Menu部分](https://www.electronjs.org/zh/docs/latest/api/menu)
|
||
|
||
```javascript
|
||
// ...
|
||
console.log(process.platform) // 平台判断
|
||
// ...
|
||
const createWindow = () => {
|
||
let mainWin = new BrowserWindow({
|
||
// ...
|
||
});
|
||
|
||
// 定义自己需要的菜单项
|
||
let menuTemp = [
|
||
{
|
||
label: "文件",
|
||
submenu: [
|
||
{
|
||
label: "打开文件",
|
||
click() {
|
||
console.log("打开文件夹")
|
||
}
|
||
},
|
||
{
|
||
type: 'separator' // 分隔符
|
||
},
|
||
{
|
||
label: "关闭文件夹"
|
||
},
|
||
{
|
||
label: "关于",
|
||
role: 'about'
|
||
},
|
||
],
|
||
},
|
||
{ label: "编辑" },
|
||
];
|
||
|
||
// 利用上述模板生成一个菜单项
|
||
let menu = Menu.buildFromTemplate(menuTemp);
|
||
|
||
// 添加到应用里
|
||
Menu.setApplicationMenu(menu);
|
||
|
||
// ...
|
||
};
|
||
|
||
// ...
|
||
|
||
```
|
||
|
||
## 菜单角色及类型
|
||
|
||
```javascript
|
||
function createWindow() {
|
||
let mainWin = new BrowserWindow({
|
||
// ...
|
||
})
|
||
|
||
// 01 自定义菜单的内容
|
||
let menuTemp = [
|
||
{
|
||
label: '角色',
|
||
submenu: [
|
||
{ label: '复制', role: 'copy' },
|
||
{ label: '剪切', role: 'cut' },
|
||
{ label: '粘贴', role: 'paste' },
|
||
{ label: '最小化', role: 'minimize' }
|
||
]
|
||
},
|
||
{
|
||
label: '类型',
|
||
submenu: [
|
||
{ label: '选项1', type: 'checkbox' },
|
||
{ label: '选项2', type: 'checkbox' },
|
||
{ label: '选项3', type: 'checkbox' },
|
||
{ type: 'separator' },
|
||
{ label: 'item1', type: 'radio' },
|
||
{ label: 'item2', type: 'radio' },
|
||
{ type: 'separator' },
|
||
{ label: 'windows', type: 'submenu', role: 'windowMenu'}
|
||
]
|
||
},
|
||
{
|
||
label: '其他',
|
||
submenu: [
|
||
{
|
||
label: '打开',
|
||
icon: 'open.png', // 自定义图标
|
||
accelerator: 'ctrl + o', // 快捷键
|
||
click() {
|
||
console.log('open 执行了')
|
||
}
|
||
}
|
||
]
|
||
}
|
||
]
|
||
|
||
// 02 依据上述数据创建一个 menu
|
||
let menu = Menu.buildFromTemplate(menuTemp)
|
||
|
||
// 03 将上述的菜单添加至 app 中
|
||
Menu.setApplicationMenu(menu)
|
||
|
||
// ...
|
||
```
|
||
|
||
## 动态创建菜单
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<html lang="en">
|
||
<head>
|
||
<!-- ... -->
|
||
</head>
|
||
<body>
|
||
<button id="addMenu">创建自定义菜单</button>
|
||
<input type="text" placeholder="输入自定义菜单项内容" id="menuCon">
|
||
<button id="addItem">添加菜单项</button>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
const { remote } = require('electron')
|
||
const Menu = remote.Menu
|
||
const MenuItem = remote.MenuItem
|
||
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
// 获取相应的元素
|
||
let addMenu = document.getElementById('addMenu')
|
||
let menuCon = document.getElementById('menuCon')
|
||
let addItem = document.getElementById('addItem')
|
||
|
||
// 自定义全局变量存放菜单项
|
||
let menuItem = new Menu()
|
||
|
||
// 生成自定义的菜单
|
||
addMenu.addEventListener('click', () => {
|
||
// 创建菜单
|
||
let menuFile = new MenuItem({ label: '文件', type: 'normal' })
|
||
let menuEdit = new MenuItem({ label: '编辑', type: 'normal' })
|
||
let customMenu = new MenuItem({ label: '自定义菜单项', submenu: menuItem })
|
||
|
||
// 将创建好的自定义菜单添加至 menu
|
||
let menu = new Menu()
|
||
menu.append(menuFile)
|
||
menu.append(menuEdit)
|
||
menu.append(customMenu)
|
||
|
||
// 将 menu 添加至 app 中显示
|
||
Menu.setApplicationMenu(menu)
|
||
})
|
||
|
||
// 动态添加菜单项
|
||
addItem.addEventListener('click', () => {
|
||
// 获取当前 input 输入框中的元素
|
||
let con = menuCon.vaule.trim()
|
||
if (con) {
|
||
menuItem.append(new MenuItem({ label: con, type: 'normal' }))
|
||
menuCon.vaule = ''
|
||
}
|
||
})
|
||
})
|
||
```
|
||
|
||
## 右键菜单的创建
|
||
|
||
```javascript
|
||
// index.js
|
||
const { remote } = require('electron')
|
||
const Menu = remote.Menu
|
||
|
||
let contextTemp = [
|
||
{lable: 'Run Code'},
|
||
{lable: '转到定义'},
|
||
{type: 'separator'},
|
||
{
|
||
lable: '其他功能',
|
||
click() {
|
||
alert('其他功能选项');
|
||
}
|
||
},
|
||
]
|
||
|
||
let menu = Menu.buildFromTemplate(contextTemp)
|
||
|
||
// 给鼠标添加监听
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
window.addEventListener('contextmenu', (ev) => {
|
||
ev.preventDefault()
|
||
menu.popup({window: remote.getCurrentWindow()})
|
||
}, false)
|
||
})
|
||
|
||
/**
|
||
* 01 创建一个自定义的菜单内容
|
||
* 02 在鼠标右击行为发生后显示出来
|
||
*/
|
||
```
|
||
|
||
## 主进程与渲染进程通信
|
||
|
||
```javascript
|
||
// main.js
|
||
const createWindow = () => {
|
||
let mainWin = new BrowserWindow({
|
||
// ...
|
||
})
|
||
|
||
let temp = [
|
||
{
|
||
label: 'send',
|
||
click() {
|
||
// 主进程主动与渲染进程发送消息
|
||
BrowserWindow.getFocusedWindow().webContents.send('mtp', '来自于主进程的消息')
|
||
}
|
||
}
|
||
]
|
||
|
||
let menu = Menu.buildFromTemplate(temp)
|
||
// ...
|
||
}
|
||
|
||
// ...
|
||
|
||
// 主进程接收消息操作
|
||
ipcMain.on('msg1', (ev, data) => {
|
||
console.log(data)
|
||
ev.sender.send('msg1Re', '来自于主进程的异步消息')
|
||
})
|
||
|
||
ipcMain.on('msg2', (ev, data) => {
|
||
console.log(data)
|
||
ev.returnValue = '来自于主进程的同步消息'
|
||
})
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
const { ipcRenderer } = require('electron')
|
||
|
||
window.onload = () => {
|
||
// 获取元素
|
||
let aBtn = document.getElementsByTagName('button')
|
||
|
||
// 01 采用异步的 API 在渲染进程中给主进程发送信息
|
||
aBtn[0].addEventListener('click', () => {
|
||
ipcRenderer.send('msg1', '来自于渲染进程的一条异步消息')
|
||
})
|
||
|
||
// 02 采用同步的 API 在渲染进程中给主进程发送信息
|
||
aBtn[1].addEventListener('click', () => {
|
||
let val = ipcRenderer.sendSync('msg2', '来自于渲染进程的一条同步消息')
|
||
alert(val)
|
||
})
|
||
|
||
// 接收消息的区域
|
||
ipcRenderer.on('msg1Re', (ev, data) => {
|
||
alert(data)
|
||
})
|
||
|
||
ipcRenderer.on('mtp', (ev, data) => {
|
||
alert(data)
|
||
})
|
||
}
|
||
```
|
||
|
||
## 渲染进程间通信
|
||
|
||
### 通过本地储存存储
|
||
|
||
```javascript
|
||
// main.js
|
||
// ...
|
||
|
||
// 定义全局变量存放主窗口 Id
|
||
let mainWinId = null
|
||
|
||
const createWindow = () => {
|
||
let mainWin = new BrowserWindow({
|
||
// ...
|
||
})
|
||
|
||
mainWinId = mainWin.id
|
||
// ...
|
||
}
|
||
|
||
// 接受其他进程发送的数据,完成后续的逻辑
|
||
ipcMain.on('openWin2', () => {
|
||
// 接收到渲染进程中按钮点击信息之后完成窗口2的打开
|
||
let subWin1 = new BrowserWindow({
|
||
// ...
|
||
parent: BrowserWindow.fromId(mainWinId), // 或定义全局变量
|
||
// ...
|
||
})
|
||
// ...
|
||
})
|
||
|
||
// ...
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
window.onload = () => {
|
||
// 先获取元素
|
||
let oBtn = document.getElementById('btn')
|
||
|
||
oBtn.addEventListener('click', () => {
|
||
ipcRenderer.send('openWin2')
|
||
|
||
// 打开窗口2之后,保存数据至本地储存
|
||
localStorage.setItem('name', '啦啦啦啦')
|
||
})
|
||
}
|
||
```
|
||
|
||
```javascript
|
||
// subWin1.js
|
||
window.onload = () => {
|
||
let oInput = document.getElementById('txt')
|
||
let val = localStorage.getItem('name')
|
||
|
||
oInput.value = val
|
||
}
|
||
```
|
||
|
||
### 通过主进程
|
||
|
||
```javascript
|
||
// main.js
|
||
|
||
// 定义全局变量存放主窗口 Id
|
||
let mainWinId = null
|
||
|
||
const createWindow = () => {
|
||
let mainWin = new BrowserWindow({
|
||
// ...
|
||
})
|
||
|
||
mainWinId = mainWin.id
|
||
// ...
|
||
}
|
||
|
||
// 接受其他进程发送的数据,完成后续的逻辑
|
||
ipcMain.on('openWin2', (_, data) => {
|
||
// 接收到渲染进程中按钮点击信息之后完成窗口2的打开
|
||
let subWin1 = new BrowserWindow({
|
||
// ...
|
||
})
|
||
// ...
|
||
|
||
// 由 index -> main* -> subWin
|
||
// 转交给进程
|
||
subWin1.webContents.on('did-finish-load', () => {
|
||
subWin1.webContents.send('its', data)
|
||
})
|
||
})
|
||
|
||
// 由 subWin -> main* -> index
|
||
ipcMain.on('stm', (_, data) => {
|
||
// 转交给进程
|
||
let mainWin = BrowserWindow.fromId(mainWinId)
|
||
mainWin.webContents.send('mti', data)
|
||
})
|
||
|
||
// ...
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
window.onload = () => {
|
||
// 先获取元素
|
||
let oBtn = document.getElementById('btn')
|
||
|
||
// 由 index* -> main -> subWin1
|
||
oBtn.addEventListener('click', () => {
|
||
ipcRenderer.send('openWin2', '来自于 index 进程')
|
||
})
|
||
|
||
// 由 subWin1 -> main -> index*
|
||
// 接受消息
|
||
ipcRenderer.on('mti', (_, data) => {
|
||
alert(data)
|
||
})
|
||
}
|
||
```
|
||
|
||
```javascript
|
||
// subWin1.js
|
||
window.onload = () => {
|
||
// ...
|
||
// 在 sub 中发送数据给 index.js
|
||
let oBtn = document.getElementById('btn')
|
||
// subWin1* -> main -> index
|
||
oBtn.addEventListener('click', () => {
|
||
ipcRenderer.send('stm', '来自于sub进程')
|
||
})
|
||
|
||
// index -> main -> subWin1*
|
||
// 接收数据
|
||
ipcRenderer.on('its', (_, data) => {
|
||
alert(data)
|
||
})
|
||
}
|
||
```
|
||
|
||
## Dialog模块
|
||
|
||
[Electron官网 Dialog文档](https://www.electronjs.org/zh/docs/latest/api/dialog)
|
||
|
||
```javascript
|
||
// index.js
|
||
window.onload = () => {
|
||
let oBtn = document.getElementById('btn')
|
||
let oBtnErr = document.getElementById('btnErr')
|
||
|
||
oBtn.addEventListener('click', () => {
|
||
remote.dialog.showOpenDialog({
|
||
defaultPath: __dirname, // 默认打开目录
|
||
buttonLabel: '请选择', // 按钮上的文字
|
||
title: '啦啦啦啦', // 对话框标题
|
||
properties: ['openFiles', 'multiSelections'], // 文件类型
|
||
filters: [ // 文件类型过滤
|
||
{'name': '代码文件', extensions: ['js', 'json', 'html']},
|
||
{'name': '图片文件', extensions: ['ico', 'jpeg', 'png']},
|
||
{'name': '媒体类型', extensions: ['avi', 'mp4', 'mp3']},
|
||
],
|
||
}).then(ret => {
|
||
alert(ret)
|
||
})
|
||
})
|
||
|
||
oBtnErr.addEventListener('click', () => {
|
||
remote.dialog.showErrorBox('自定义标题', '当前错误内容')
|
||
})
|
||
}
|
||
```
|
||
|
||
## shell 与 iframe
|
||
|
||
### shell
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<html lang="en">
|
||
<head>
|
||
<!-- ... -->
|
||
</head>
|
||
<body>
|
||
<h2>shell and iframe</h2>
|
||
<!-- 默认行为是在当前页面打开网页 -->
|
||
<a id="openUrl" href="https://cantyonion.site">打开url</a>
|
||
<br><br>
|
||
<button id="openFolder">打开目录</button>
|
||
<script src="index.js"></script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
window.onload = () => {
|
||
// 1 获取元素
|
||
let oBtn1 = document.getElementById('openUrl')
|
||
let oBtn2 = document.getElementById('openFolder')
|
||
|
||
oBtn1.addEventListener('click', (ev) => {
|
||
ev.preventDefault() // 阻止默认行为
|
||
|
||
let urlPath = oBtn1.getAttribute('href')
|
||
|
||
// 打开外部浏览器
|
||
shell.openExternal(urlPath)
|
||
})
|
||
|
||
oBtn2.addEventListener('click', () => {
|
||
// 打开当前目录
|
||
shell.showItemInFolder(path.resolve(__filename))
|
||
})
|
||
}
|
||
```
|
||
|
||
### iframe
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<html lang="en">
|
||
<head>
|
||
<!-- ... -->
|
||
</head>
|
||
<body>
|
||
<iframe src="https://cantyonion.site" frameborder="0" id="webview"></iframe>
|
||
<script src="index.js"></script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
ipcRenderer.on('open', () => {
|
||
let iframe = document.getElementById('webview')
|
||
iframe.src = 'https://cantyonion.site/git/'
|
||
})
|
||
```
|
||
|
||
``` javascript
|
||
// main.js
|
||
const createWindow = () => {
|
||
let mainWin = new BrowserWindow({
|
||
// ...
|
||
})
|
||
|
||
let tmp = [
|
||
{
|
||
label: '菜单',
|
||
submenu: [
|
||
{
|
||
label: '关于',
|
||
click() {
|
||
shell.openExternal('https://cantyonion.site')
|
||
}
|
||
},
|
||
{
|
||
label: '打开',
|
||
click() {
|
||
BrowserWindow.getFocusedWindow().webContents.send('open')
|
||
}
|
||
},
|
||
]
|
||
}
|
||
]
|
||
|
||
let menu = Menu.buildFromTemplate(tmp)
|
||
Menu.setApplicationMenu(menu)
|
||
// ...
|
||
}
|
||
// ...
|
||
|
||
```
|
||
|
||
## 消息通知
|
||
|
||
前往[MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Notification)查看详细内容
|
||
|
||
```javascript
|
||
window.onload = () => {
|
||
let oBtn = document.getElementById('btn')
|
||
|
||
oBtn.addEventListener('click', () => {
|
||
let option = {
|
||
title: '啦啦啦', // 通知标题
|
||
body: 'ok,哈哈哈哈', // 信息体
|
||
icon: 'c.png' // 图标
|
||
}
|
||
|
||
let mayNotification = new window.Notification(option.title, option)
|
||
|
||
mayNotification.onclick = () => {
|
||
alert("点击了消息页卡")
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
## 全局快捷键
|
||
|
||
```javascript
|
||
// main.js
|
||
// ...
|
||
app.on('ready', () => {
|
||
// 注册
|
||
let ret = globalShortcut.register('ctrl + q', () => {
|
||
console.log("快捷键注册成功")
|
||
})
|
||
|
||
if (!ret) {
|
||
console.log('注册失败')
|
||
}
|
||
|
||
// 判断某个快捷键是否已经注销
|
||
console.log(globalShortcut.isRegistered('ctrl + q'))
|
||
})
|
||
|
||
app.on('will-quit', () => {
|
||
globalShortcut.unregister('ctrl + q')
|
||
|
||
// 自动注销使用快捷键
|
||
globalShortcut.unregisterAll()
|
||
})
|
||
```
|
||
|
||
## 剪切板模块
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<html lang="en">
|
||
<head>
|
||
<!-- ... -->
|
||
</head>
|
||
<body>
|
||
<h2>剪切板</h2>
|
||
<input type="text" placeholder="输入需要复制的内容">
|
||
<button>复制</button>
|
||
<br><br>
|
||
<input type="text" placeholder="将内容粘贴至此处">
|
||
<button>粘贴</button>
|
||
<br><br>
|
||
<button id="clipImg">将图片拷贝至剪切板再粘贴至界面</button>
|
||
<script src="index.js"></script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
```javascript
|
||
// index.js
|
||
// ...
|
||
|
||
window.onload = () => {
|
||
// 获取元素
|
||
let aBtn = document.getElementsByTagName('button')
|
||
let aInput = document.getElementsByTagName('input')
|
||
let oBtn = document.getElementById('clipImg')
|
||
let ret = null
|
||
|
||
aBtn[0].onclick = () => {
|
||
// 复制内容
|
||
ret = clipboard.writeText(aInput[0].value)
|
||
}
|
||
|
||
aBtn[1].onclick = () => {
|
||
// 粘贴内容
|
||
aInput[1].value = clipboard.readText(ret)
|
||
}
|
||
|
||
oBtn.onclick = () => {
|
||
// 将图片放置于剪切板的时候要求图片类型属于 nativeImage 类型
|
||
let oImage = nativeImage.createFromPath('c.png')
|
||
clipboard.writeImage(oImage)
|
||
|
||
// 将剪切板中的图片作为 DOM 元素显示在界面上
|
||
let oImg = clipboard.readImage()
|
||
let oImgDom = new Image()
|
||
oImgDom.src = oImg.toDataURL() // 转换为base64
|
||
document.body.appendChild(oImgDom)
|
||
}
|
||
}
|
||
```
|
||
|