package.json
:
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "my demo",
"main": "main.js",
"scripts": {
"dev": "electron . --inspect=5858",
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"win": "electron-builder --win --x64"
},
"author": "icestone",
"license": "MIT",
"devDependencies": {
"@electron-forge/cli": "^6.1.1",
"electron": "23.1.3",
"electron-builder": "^23.6.0"
},
"win": {
"icon": "icons/icon.ico",
"target": [
{
"target": "nsis",
"arch": [
"x64",
"ia32"
]
}
]
}
}
main.js
const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');
const createWindow = () => {
const win = new BrowserWindow({
width: 1000,
height: 900,
webPreferences: {
preload: path.join(__dirname, './preload.js'),
},
})
require('./src/js/menu'),
ipcMain.handle('ping', () => 'pong');
win.loadFile('index.html');
}
// 下面两种监听都可以
/*app.whenReady().then(() => {
createWindow()
})*/
app.on('ready', () => {
createWindow()
})
// 监听关闭时调用
app.on('window-all-closed', () => {
console.log('close window')
if (process.platform !== 'darwin') app.quit()
})
index.html
:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
head>
<body>
<h1>Hello World!h1>
<p>
We are using Node.js <span id="node-version">span>,
Chromium <span id="chrome-version">span>,
and Electron <span id="electron-version">span>.
p>
body>
html>
run:
win.on('close',function () {
console.log('window is close!')
})
它的完整代码应该是:
const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');
const createWindow = () => {
const win = new BrowserWindow({
width: 1000,
height: 900,
webPreferences: {
preload: path.join(__dirname, './preload.js'),
},
})
ipcMain.handle('ping', () => 'pong');
win.loadFile('index.html');
win.on('close',function () {
console.log('window is close!')
})
}
// 下面两种监听都可以
/*app.whenReady().then(() => {
createWindow()
})*/
app.on('ready', () => {
createWindow()
})
// 监听关闭时调用
app.on('window-all-closed', () => {
console.log('close window')
if (process.platform !== 'darwin') app.quit()
})
ready
dom-ready
did-finsh-load
window-all-closed
before-quit
will-quit
quit
closed
例如下面的main.js演示:
const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');
const createWindow = () => {
const win = new BrowserWindow({
width: 1000,
height: 900,
webPreferences: {
preload: path.join(__dirname, './preload.js'),
},
})
ipcMain.handle('ping', () => 'pong');
win.loadFile('index.html');
win.webContents.on('did-finish-load', () => {
console.log('did-finish-load');
})
win.webContents.on('dom-ready', () => {
console.log('dom-ready');
})
win.on('close', function () {
console.log('close')
})
}
// 下面两种监听都可以
/*app.whenReady().then(() => {
createWindow()
})*/
app.on('ready', () => {
console.log('ready')
createWindow()
});
// 监听关闭时调用
app.on('window-all-closed', () => {
console.log('all close window')
if (process.platform !== 'darwin') app.quit()
});
app.on('before-quit', function () {
console.log('before-quit')
});
app.on('will-quit', function () {
console.log('will-quit');
});
app.on('quit', function () {
console.log('quit');
});
run:
package.json中的script:
"scripts": {
"dev": "electron . --inspect=5858",
"start": "electron .",
"nodemon": "nodemon --main.js --exec npm run dev"
},
这样就可以使用nodemon监听main.js的改动了
每次打开窗口默认会在屏幕的中央进行显示,如果想要更改,可以在mian.js中使用x
,y
来更改:
const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');
const createWindow = () => {
const win = new BrowserWindow({
x: 200,
y: 200,
width: 1000,
height: 900,
webPreferences: {
preload: path.join(__dirname, './preload.js'),
},
})
ipcMain.handle('ping', () => 'pong');
win.loadFile('index.html');
win.webContents.on('did-finish-load', () => {
console.log('did-finish-load');
})
win.webContents.on('dom-ready', () => {
console.log('dom-ready');
})
win.on('close', function () {
console.log('close')
})
}
// 下面两种监听都可以
/*app.whenReady().then(() => {
createWindow()
})*/
app.on('ready', () => {
console.log('ready')
createWindow()
});
// 监听关闭时调用
app.on('window-all-closed', () => {
console.log('all close window')
if (process.platform !== 'darwin') app.quit()
});
app.on('before-quit', function () {
console.log('before-quit')
});
app.on('will-quit', function () {
console.log('will-quit');
});
app.on('quit', function () {
console.log('quit');
});
然后他就更改了:
但是此时,可能会先出现窗口,白屏一瞬间之后再加载内容,那么此时就可以使用:show: false
设置一下
const win = new BrowserWindow({
show: false,
x: 200,
y: 200,
width: 1000,
height: 900,
webPreferences: {
preload: path.join(__dirname, './preload.js'),
},
})
win.on("ready-to-show", function () {
win.loadFile('index.html');
})
这里监听了ready-to-show
,在这个阶段才调用加载index.html
const win = new BrowserWindow({
show: false,
x: 200,
y: 200,
width: 1000,
height: 900,
maxHeight: 1000,
maxWidth: 1100,
minHeight: 500,
minWidth: 1000
})
使用resizable:false
:
const win = new BrowserWindow({
show: false,
x: 200,
y: 200,
width: 1000,
height: 900,
maxHeight: 1000,
maxWidth: 1100,
minHeight: 500,
minWidth: 1000,
resizable:false
})
const win = new BrowserWindow({
// show: false,
x: 200,
y: 200,
width: 1000,
height: 900,
// 设置最大尺寸
maxHeight: 1000,
maxWidth: 1100,
// 设置最小尺寸
minHeight: 500,
minWidth: 1000,
// 禁止缩放窗口
// resizable:false
title:'在main.js中设置的title'
})
const win = new BrowserWindow({
// show: false,
x: 200,
y: 200,
width: 1000,
height: 900,
// 设置最大尺寸
maxHeight: 1000,
maxWidth: 1100,
// 设置最小尺寸
minHeight: 500,
minWidth: 1000,
// 禁止缩放窗口
// resizable:false
title:'在main.js中设置的title',
icon:'./lg.ico'
})
如图:
frame:false
,默认为true
运行:
那么此时窗口无法进行拖动
transparent: true
运行:
const win = new BrowserWindow({
// show: false,
x: 200,
y: 200,
width: 1000,
height: 900,
// 设置最大尺寸
maxHeight: 1000,
maxWidth: 1100,
// 设置最小尺寸
minHeight: 500,
minWidth: 1000,
// 禁止缩放窗口
// resizable:false
title: '在main.js中设置的title',
icon: './lg.ico',
// 不显示默认窗口和菜单
// frame:false
// 透明窗体
// transparent: true
// 隐藏menu
autoHideMenuBar: true
})
ctrl+shift+i
一般情况下,在index.html
中引用的js文件是无法导入nodejs中的包的,例如下面的代码:
index.js
:
const o = require('electron');
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
// 点击打开一个新窗口
const oBtn = document.getElementById('btn')
oBtn.addEventListener('click', () => {
})
})
在第一行导入了包,那么在应用的控制台中:
默认情况下是不允许渲染进程中的js直接和nodejs进行交互,那么在开发中想要和nodejs进行交互,可以在main.js中开启:
webPreferences: {
nodeIntegration: true,
contextIsolation
:
false
}
完整的main.js:
const path = require('path');
const {app, BrowserWindow, ipcMain} = require('electron');
const createWindow = () => {
const win = new BrowserWindow({
x: 200,
y: 200,
width: 1000,
height: 900,
title: '在main.js中设置的title',
icon: './lg.ico',
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
win.loadFile('index.html');
}
// 监听关闭时调用
app.on('window-all-closed', () => {
console.log('all close window')
if (process.platform !== 'darwin') app.quit()
});
然后就不会报错了
例如像下面,在渲染进程中使用了BrowserWindow
,虽然可以导入,但是不被允许:
// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow} = require('electron');
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
// 点击打开一个新窗口
const oBtn = document.getElementById('btn')
oBtn.addEventListener('click', () => {
let indexMin = new BrowserWindow({
width: 1000,
height: 900
})
indexMin.loadFile('../views/list.html');
indexMin.on("close", () => {
indexMin = null;
})
})
})
报错:
index.js:8 Uncaught TypeError: BrowserWindow is not a constructor
at HTMLButtonElement.<anonymous> (index.js:8:24)
main.js中的主要代码:
const remote = require("@electron/remote/main") //1
remote.initialize()//2
remote.enable(win.webContents)//3
mian.js
的完整代码:
const {app, BrowserWindow} = require('electron');
const remote = require("@electron/remote/main") //1
remote.initialize()//2
const createWindow = () => {
const win = new BrowserWindow({
x: 200,
y: 200,
width: 1000,
height: 900,
title: '在main.js中设置的title',
icon: './lg.ico',
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
},
})
win.loadFile('index.html');
remote.enable(win.webContents)//3
}
app.on('ready', () => {
console.log('ready')
createWindow()
});
// 监听关闭时调用
app.on('window-all-closed', () => {
console.log('all close window')
if (process.platform !== 'darwin') app.quit()
});
index.js
:
// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow} = require("@electron/remote");
console.log('当前路径')
console.log(__dirname)
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
// 点击打开一个新窗口
const oBtn = document.getElementById('btn')
oBtn.addEventListener('click', () => {
let indexMin = new BrowserWindow({
width: 1000,
height: 900
})
indexMin.loadFile('./src/views/list.html');
indexMin.on("close", () => {
indexMin = null;
})
})
})
要注意这里的引用:
const {BrowserWindow} = require("@electron/remote");
index.html
:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>title>
<link rel="stylesheet" type="text/css" href="./src/css/index.css"/>
head>
<body>
<div class="container">
<div class="header">
<div class="btn">minWindowdiv>
<div class="btn">maxWindowdiv>
<div class="btn">closediv>
div>
div>
<script src="./index.js">script>
body>
html>
index.js
:
// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow, ipcMain, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();
console.log('当前路径')
console.log(__dirname)
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
// 点击打开一个新窗口
const btns = document.getElementsByClassName('btn')
const close = btns[2];
const maxWindow = btns[1];
const minWindow = btns[0];
close.addEventListener('click', () => {
console.log('关闭')
mainWin.close();
})
maxWindow.addEventListener('click', () => {
console.log('最大化')
/* console.log('是否为最大化')
console.log(mainWin.isMaximizable());*/
if (!mainWin.isMaximized()) {
mainWin.maximize()
} else {
console.log('恢复尺寸')
// 让当前窗口回到原始状态
mainWin.restore();
}
})
minWindow.addEventListener('click', () => {
console.log('最小化')
if (!mainWin.isMinimized()) {
mainWin.minimize()
} else {
mainWin.restore();
}
})
})
监听窗口关闭之前的状态:
index.js
:
// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow, ipcMain, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();
console.log('当前路径')
console.log(__dirname)
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
window.onbeforeunload = function () {
console.log('关闭窗口')
return false;
}
// 点击打开一个新窗口
const btns = document.getElementsByClassName('btn')
const close = btns[2];
const maxWindow = btns[1];
const minWindow = btns[0];
close.addEventListener('click', () => {
console.log('关闭')
mainWin.close();
})
maxWindow.addEventListener('click', () => {
console.log('最大化')
/*console.log('是否为最大化')
console.log(mainWin.isMaximizable());*/
if (!mainWin.isMaximized()) {
mainWin.maximize()
} else {
console.log('恢复尺寸')
// 让当前窗口回到原始状态
mainWin.restore();
}
})
minWindow.addEventListener('click', () => {
console.log('最小化')
if (!mainWin.isMinimized()) {
mainWin.minimize()
} else {
mainWin.restore();
}
})
})
index.html
:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>title>
<link rel="stylesheet" type="text/css" href="./src/css/index.css"/>
head>
<body>
<div class="container">
<div class="header">
<div class="btn">minWindowdiv>
<div class="btn">maxWindowdiv>
<div class="btn">closediv>
div>
div>
<div class="alert">
确认关闭?
<button class="close">yes!button>
<button class="notClose">no!button>
div>
<script src="./index.js">script>
body>
html>
这里主要是index.js
中的:
window.onbeforeunload = function () {
console.log('关闭窗口')
return false;
}
index.html
:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>title>
<link rel="stylesheet" type="text/css" href="./src/css/index.css"/>
head>
<body>
<div class="container">
<div class="header">
<div class="btn">minWindowdiv>
<div class="btn">maxWindowdiv>
<div class="btn">closediv>
div>
div>
<div class="alert">
确认关闭?
<button class="close">yes!button>
<button class="notClose">no!button>
div>
<script src="./index.js">script>
body>
html>
index.css
:
.container {
display: flex;
flex-direction: column;
}
.header {
display: flex;
width: 100%;
flex-direction: row;
justify-content: end;
background: #8c8c73;
}
.header div {
padding-right: 20px;
}
body {
background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
}
.alert {
display: none;
}
index.js
:
// BrowserWindow 是个主进程,虽然可以导入,但是在渲染进程中是不允许这样做的
const {BrowserWindow, ipcMain, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();
console.log('当前路径')
console.log(__dirname)
// dom加载完之后执行
window.addEventListener('DOMContentLoaded', function () {
window.onbeforeunload = function () {
console.log('关闭窗口')
const alert = document.getElementsByClassName('alert')[0];
alert.style.display = 'flex';
const yesBtn = document.getElementsByClassName('close')[0];
const noBtn = document.getElementsByClassName('notClose')[0];
yesBtn.addEventListener('click', () => {
mainWin.destroy();
})
noBtn.addEventListener('click', () => {
alert.style.display = 'none';
})
return false;
}
// 点击打开一个新窗口
const btns = document.getElementsByClassName('btn')
const close = btns[2];
const maxWindow = btns[1];
const minWindow = btns[0];
close.addEventListener('click', () => {
console.log('关闭')
mainWin.close();
})
maxWindow.addEventListener('click', () => {
console.log('最大化')
/*console.log('是否为最大化')
console.log(mainWin.isMaximizable());*/
if (!mainWin.isMaximized()) {
mainWin.maximize()
} else {
console.log('恢复尺寸')
// 让当前窗口回到原始状态
mainWin.restore();
}
})
minWindow.addEventListener('click', () => {
console.log('最小化')
if (!mainWin.isMinimized()) {
mainWin.minimize()
} else {
mainWin.restore();
}
})
})
main.js
:
const {app, BrowserWindow} = require('electron')
const path = require('path')
const remote = require("@electron/remote/main") //1
remote.initialize()//2
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
frame: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
win.loadFile('index.html')
win.on('close', function () {
console.log('close')
})
remote.enable(win.webContents)//3
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
一般情况下创建的子窗口,在操作子窗口时,父窗口依旧可以操作:
main.js
:
const {app, BrowserWindow} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
const createWindow = () => {
// 创建浏览窗口
const win = new BrowserWindow({
width: 800,
height: 600,
title: '子窗口及模态窗口',
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 加载 index.html
win.loadFile('index.html')
//3
remote.enable(win.webContents)
// 打开开发工具
// mainWindow.webContents.openDevTools()
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// 在 macOS 系统内, 如果没有已开启的应用窗口
// 点击托盘图标时通常会重新创建一个新窗口
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
index.html
:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>title>
head>
<body>
<div class="container">
<button id="btn">新增窗口button>
div>
<script src="./index.js">script>
body>
html>
index.js
:
const {BrowserWindow, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();
window.addEventListener('DOMContentLoaded', () => {
const btn = document.getElementById("btn");
btn.addEventListener('click', () => {
let subWin = new BrowserWindow({
parent: mainWin,
width: 1000,
height: 900
})
subWin.loadFile('sub.html')
subWin.on('close', () => {
subWin = null;
})
})
})
run:
此时是可以拖动父窗口的
但是使用模态窗口就可以避免这个问题,
模态窗口
main.js
:
const {app, BrowserWindow} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
const createWindow = () => {
// 创建浏览窗口
const win = new BrowserWindow({
width: 800,
height: 600,
title: '子窗口及模态窗口',
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 加载 index.html
win.loadFile('index.html')
//3
remote.enable(win.webContents)
// 打开开发工具
// mainWindow.webContents.openDevTools()
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// 在 macOS 系统内, 如果没有已开启的应用窗口
// 点击托盘图标时通常会重新创建一个新窗口
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
index.html
:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>title>
head>
<body>
<div class="container">
<button id="btn">新增窗口button>
div>
<script src="./index.js">script>
body>
html>
index.js
:
const {BrowserWindow, getCurrentWindow} = require("@electron/remote");
let mainWin = getCurrentWindow();
window.addEventListener('DOMContentLoaded', () => {
const btn = document.getElementById("btn");
btn.addEventListener('click', () => {
let subWin = new BrowserWindow({
parent: mainWin,
width: 1000,
height: 900,
modal: true
})
subWin.loadFile('sub.html')
subWin.on('close', () => {
subWin = null;
})
})
})
run:
注意,这里主要起作用的是index.js
的:
modal: true
const {app, BrowserWindow, Menu} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
const createWindow = () => {
// 创建浏览窗口
const win = new BrowserWindow({
width: 800,
height: 600,
title: '自定义菜单',
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 1.定义自己需要的菜单
let menuMap = [
{label: '文件'},
{label: '编辑'},
];
// 2.利用上面的模板构建菜单项:
let menu = Menu.buildFromTemplate(menuMap);
// 3.将上述的自定义菜单添加到应用
Menu.setApplicationMenu(menu);
win.loadFile('index.html')
//3
remote.enable(win.webContents)
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
主要分三步:
const {app, BrowserWindow, Menu} = require('electron')
// 1.定义自己需要的菜单
let menuMap = [
{label: '文件'},
{label: '编辑'},
];
let menu = Menu.buildFromTemplate(menuMap);
// 3.将上述的自定义菜单添加到应用
Menu.setApplicationMenu(menu);
win.loadFile('index.html')
const {app, BrowserWindow, Menu} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
const createWindow = () => {
// 创建浏览窗口
const win = new BrowserWindow({
width: 800,
height: 600,
title: '自定义菜单',
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 1.定义自己需要的菜单
let menuMap = [
{
label: '文件',
submenu: [
{
label: '打开文件夹',
click() {
console.log('open someone dir')
}
},
{
label: '打开文件'
},
{
label: '关于',
role: 'about'
}
]
},
{label: '编辑'},
];
// 2.利用上面的模板构建菜单项:
let menu = Menu.buildFromTemplate(menuMap);
// 3.将上述的自定义菜单添加到应用
Menu.setApplicationMenu(menu);
// 加载 index.html
win.loadFile('index.html')
//3
remote.enable(win.webContents)
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
这里主要是menuMap
发生变化,里面存储的click
函数,在文件
中定义的有其他的二级菜单
let menuMap = [
{
label: '文件',
submenu: [
{
label: '打开文件夹',
click() {
console.log('open someone dir')
}
},
// 分割线
{
type: 'separator'
},
{
label: '打开文件',
},
{
label: '关于',
role: 'about'
}
]
},
{label: '编辑'},
];
例如上面的,传入type`的值表示不同的分割线
let menuMap = [
{
label: '内置角色',
submenu: [
{
label: '复制',
role: 'copy'
},
{
label: '剪贴',
role: 'cut'
},
{
label: '粘贴',
role: 'paste'
},
{
label: '最小化',
role: 'minimize'
}
]
}];
let menuMap = [
{
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'
}
]
}]
let menuMap = [
{
label: '其他',
submenu: [
{
label: '打开',
icon: './open.png',
accelerator: 'ctrl+o',
click() {
console.log('open操作执行了!')
}
},
]
}
]
main.js
:
const {app, BrowserWindow} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
const createWindow = () => {
// 创建浏览窗口
const win = new BrowserWindow({
width: 800,
height: 600,
title: 'demo页面',
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 加载 index.html
win.loadFile('index.html')
//3
remote.enable(win.webContents)
// 打开开发工具
// mainWindow.webContents.openDevTools()
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// 在 macOS 系统内, 如果没有已开启的应用窗口
// 点击托盘图标时通常会重新创建一个新窗口
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
index.html
:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>title>
head>
<body>
<h1>自定义菜单h1>
<div class="container">
<button id="add">创建自定义菜单button>
<input type="text" value="输入自定义菜单项内容" id="menuVal">
<button id="addMenu">添加菜单项button>
div>
<script src="./index.js">script>
body>
html>
index.js
:
const {BrowserWindow, Menu, MenuItem} = require("@electron/remote");
console.log('当前路径')
console.log(__dirname)
// 自定义全局变量
let menuItem = new Menu();
window.addEventListener('DOMContentLoaded', () => {
let addBtn = document.getElementById('add');
let addMenuBtn = document.getElementById('addMenu');
let input = document.getElementById('menuVal');
// 生成自定义的菜单:
addBtn.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);
})
addMenuBtn.addEventListener('click', () => {
// 获取当前input输入框的内容
const con = input.value.trim();
if (con) {
menuItem.append(new MenuItem({
label: con, type: 'normal'
}))
input.value = '';
}
})
})
运行:
mian.js
:
const {app, BrowserWindow} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
const createWindow = () => {
// 创建浏览窗口
const win = new BrowserWindow({
width: 800,
height: 600,
title: '右键菜单',
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 加载 index.html
win.loadFile('index.html')
//3
remote.enable(win.webContents)
// 打开开发工具
// mainWindow.webContents.openDevTools()
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// 在 macOS 系统内, 如果没有已开启的应用窗口
// 点击托盘图标时通常会重新创建一个新窗口
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
index.html
:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>title>
head>
<body>
<h1>你好!h1>
<div class="container">
div>
<script src="./index.js">script>
body>
html>
index.js
:
const {Menu, getCurrentWindow} = require("@electron/remote");
const remote = require("@electron/remote/main")
let mainWin = getCurrentWindow();
// 创建一个自定义的菜单内容
let contextTemp = [
{label: 'Run Code'},
{label: '转到定义'},
{type: 'separator'},
{
label: '其他功能',
click() {
console.log('其他功能被点击了')
}
},
]
// 依据上面模板来创建menu
let menu = Menu.buildFromTemplate(contextTemp);
// 在鼠标右击行为后显示出来
window.addEventListener('DOMContentLoaded', () => {
// 监听右击
window.addEventListener('contextmenu', (ev) => {
ev.preventDefault();
menu.popup({
window: mainWin
})
}, false)
})
监听页面元素点击,渲染进程向主进程发消息:
index.html
<button id="one">渲染到主异步操作button>
<br>
<button id="two">渲染到主同步操作button>
index.js
const {
ipcRenderer
} = require('electron')
window.onload = function () {
const aBtn = document.getElementById('one');
const twoBtn = document.getElementById('two');
// 异步发送消息
// 通过异步api在渲染进程中给主进程发送消息
aBtn.addEventListener('click', () => {
ipcRenderer.send('msg1', '来自渲染进程的异步消息');
})
// 接收来自主进程的异步消息
ipcRenderer.on('msg1Re', (ev, data) => {
console.log('来自主进程的data:')
console.log(data)
})
// 同步发送消息
twoBtn.addEventListener('click', () => {
let val = ipcRenderer.sendSync('msg2', '同步消息')
console.log("val:")
console.log(val)
})
}
main.js
const {app, BrowserWindow, ipcMain, Menu} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
let temp = [
{
label: 'send',
click() {
BrowserWindow.getFocusedWindow().webContents.send('mtp','来自于主进程的消息')
}
}
]
let menu = Menu.buildFromTemplate(temp);
Menu.setApplicationMenu(menu);
const createWindow = () => {
// 创建浏览窗口
const win = new BrowserWindow({
width: 800,
height: 600,
title: '主进程与渲染进程之间通讯',
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 加载 index.html
win.loadFile('index.html')
win.webContents.openDevTools();
//3
remote.enable(win.webContents)
// 打开开发工具
// mainWindow.webContents.openDevTools()
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// 在 macOS 系统内, 如果没有已开启的应用窗口
// 点击托盘图标时通常会重新创建一个新窗口
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
// 主进程接受消息
ipcMain.on('msg1', (ev, data) => {
console.log('data:')
console.log(data)
// 给渲染进程发送消息
ev.sender.send('msg1Re', '这是一条来自主进程的异步消息')
})
ipcMain.on('msg2', (ev, data) => {
console.log(data)
ev.returnValue = '来自于主进程的同步消息'
})
上面代码中主要是ipcMain.on
来接收渲染进程发送来的消息
主进程可以这样接收并返回:
ipcMain.on('msg1', (ev, data) => {
console.log('data:')
console.log(data)
// 给渲染进程发送消息
ev.sender.send('msg1Re', '这是一条来自主进程的异步消息')
})
ipcMain.on('msg2', (ev, data) => {
console.log(data)
// 给渲染进程发送消息
ev.returnValue = '来自于主进程的同步消息'
})
渲染进程的接收:
ipcRenderer.on('msg1Re', (ev, data) => {
console.log('来自主进程的data:')
console.log(data)
})
// 同步发送消息
twoBtn.addEventListener('click', () => {
let val = ipcRenderer.sendSync('msg2', '同步消息')
console.log("val:")
console.log(val)
})
上面的代码中,渲染进程向主进程发送消息,并接收
主线程
:
let temp = [
{
label: 'send',
click() {
BrowserWindow.getFocusedWindow().webContents.send('mtp','来自于主进程的消息')
}
}
]
let menu = Menu.buildFromTemplate(temp);
Menu.setApplicationMenu(menu);
上面的代码中,设置了一个点击事件,点击触发向当前获取焦点的窗口发送消息
渲染进程:
ipcRenderer.on('mtp', (ev, data) => {
console.log(data)
})
完成代码:
main.js
const {app, BrowserWindow, ipcMain, Menu} = require('electron')
//1
const remote = require("@electron/remote/main")
//2
remote.initialize()
let temp = [
{
label: 'send',
click() {
BrowserWindow.getFocusedWindow().webContents.send('mtp','来自于主进程的消息')
}
}
]
let menu = Menu.buildFromTemplate(temp);
Menu.setApplicationMenu(menu);
const createWindow = () => {
// 创建浏览窗口
const win = new BrowserWindow({
width: 800,
height: 600,
title: '主进程与渲染进程之间通讯',
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 加载 index.html
win.loadFile('index.html')
win.webContents.openDevTools();
//3
remote.enable(win.webContents)
// 打开开发工具
// mainWindow.webContents.openDevTools()
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// 在 macOS 系统内, 如果没有已开启的应用窗口
// 点击托盘图标时通常会重新创建一个新窗口
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
// 主进程接受消息
ipcMain.on('msg1', (ev, data) => {
console.log('data:')
console.log(data)
// 给渲染进程发送消息
ev.sender.send('msg1Re', '这是一条来自主进程的异步消息')
})
ipcMain.on('msg2', (ev, data) => {
console.log(data)
ev.returnValue = '来自于主进程的同步消息'
})
index.js
const {
ipcRenderer
} = require('electron')
window.onload = function () {
const aBtn = document.getElementById('one');
const twoBtn = document.getElementById('two');
// 异步发送消息
// 通过异步api在渲染进程中给主进程发送消息
aBtn.addEventListener('click', () => {
ipcRenderer.send('msg1', '来自渲染进程的异步消息');
})
// 接收来自主进程的异步消息
ipcRenderer.on('msg1Re', (ev, data) => {
console.log('来自主进程的data:')
console.log(data)
})
// 同步发送消息
twoBtn.addEventListener('click', () => {
let val = ipcRenderer.sendSync('msg2', '同步消息')
console.log("val:")
console.log(val)
})
ipcRenderer.on('mtp', (ev, data) => {
console.log(data)
})
}
index.html
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>title>
head>
<body>
<h1>渲染进程与主进程通信h1>
<div class="container">
<button id="one">渲染到主异步操作button>
<br>
<button id="two">渲染到主同步操作button>
div>
<script src="./index.js">script>
body>
html>