首先npm init -y
然后项目目录下:
npm install electron --save-dev
或
npm i -D electron@latest
npx electron -v
查看是否安装成功!
或者
./node_modules/.bin/electron -v
使用./node_modules/.bin/electron
可查看软件界面
如果出现此错误:./node_modules/.bin/electron : 无法加载文件 E:\Project\electron\node_modules.bin\electro
n.ps1,因为在此系统上禁止运行脚本。
管理员CMD执行此命令
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
不要全局安装
npm install electron -S
准备一个html文件
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>Documenttitle>
head>
<body>
<h1>Hello World!h1>
body>
html>
写main.js
var electron = require('electron')
//引用app
var app = electron.app
//窗口引用
var BrowserWindow = electron.BrowserWindow
var mainWindow = null
//声明要打开的主窗口
app.on('ready',()=>{
mainWindow = new BrowserWindow({
width:600,
height:600
})
mainWindow.loadFile('index.html')
mainWindow.on('closed',()=>{
mainWindow = null
})
})
此时终端执行命令:
npm init --yes
发现帮我们写好了package.json
此时执行electron .
执行程序
执行成功!
在目录下新建info.txt
写入内容
新建render文件夹
在文件夹下新建index.js文件
修改html内容
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>Documenttitle>
head>
<body>
<button id="btn">内容button>
<div id="info">
div>
<script src="./render/index.js">script>
body>
html>
修改main.js
app.on(‘ready’,()=>{})
webPreferences:{
nodeIntegration:true,
contextIsolation:false
}
var electron = require('electron')
//引用app
var app = electron.app
//窗口引用
var BrowserWindow = electron.BrowserWindow
var mainWindow = null
//声明要打开的主窗口
app.on('ready',()=>{
mainWindow = new BrowserWindow({
width:600,
height:600,
webPreferences:{
nodeIntegration:true,
contextIsolation:false
}
})
mainWindow.loadFile('index.html')
mainWindow.on('closed',()=>{
mainWindow = null
})
})
此时我们写index.js文件
var fs = require('fs')
window.onload= function(){
var btn = this.document.querySelector('#btn')
var info = this.document.querySelector('#info')
btn.onclick = function(){
fs.readFile("info.txt",(err,data)=>{
info.innerHTML = data
})
}
}
目录结构:
控制台输入
electron .
测试
点击按钮
成功渲染出内容,执行成功!
新打开窗口,两个窗口不能通信
现已移除需要新安装
npm install --save @electron/remote
main.js
var electron = require('electron')
//引用app
var app = electron.app
//窗口引用
var BrowserWindow = electron.BrowserWindow
var mainWindow = null
//声明要打开的主窗口
app.on('ready',()=>{
mainWindow = new BrowserWindow({
width:600,
height:600,
webPreferences:{
nodeIntegration:true,
contextIsolation:false,
enableRemoteModule:true
}
})
require('@electron/remote/main').initialize()
require('@electron/remote/main').enable(mainWindow.webContents)
mainWindow.loadFile('demo.html')
mainWindow.on('closed',()=>{
mainWindow = null
})
})
demo.html
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>Documenttitle>
head>
<body>
<button id="btn">打开新窗口button>
<script src="./render/demo.js">script>
body>
html>
demo.js
const btn = this.document.querySelector('#btn')
const {BrowserWindow} = require('@electron/remote')
window.onload = function(){
btn.onclick = ()=>{
newWin = new BrowserWindow({
width:200,
height: 300,
})
newWin.loadFile('new.html')
newWin.on('closed',()=>{
newWin = null
})
}
}
new.html
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>Documenttitle>
head>
<body background="red">
<h1>我是测试弹出窗口h1>
body>
html>
测试打开新窗口成功!!!
跨平台桌面应用程序!
简单!!
可以使用纯JavaScript调用丰富的原生APIs来创建桌面应用。
专注于桌面应用。
安装
初始化package.json文件
npm init -y
安装electron
cnpm i electron -S
package.json
{
"name": "electron",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {},
"devDependencies": {
"@electron/remote": "^2.0.7"
}
}
我们加入配置项
注意覆盖,完整json文件
{
"name": "ele",
"version": "1.0.0",
"description": "",
"main": "main.js",
"dependencies": {
"electron": "^17.1.2",
"electron-reloader": "^1.2.3"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"electron": "electron .",
"watch": "watchify app/appEntry.js -t babelify -o public/js/bundle.js --debug --verbose",
"package": "electron-packager ./ DemoApps --overwrite --app-version=1.0.0 --platform=win32 --arch=all --out=../DemoApps --version=1.2.1 --icon=./public/img/app-icon.icns"
},
"devDependencies": {
"babel": "^6.5.2",
"babel-plugin-transform-es2015-spread": "^6.8.0",
"babel-plugin-transform-object-rest-spread": "^6.8.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.5.0",
"babelify": "^7.3.0",
"browserify": "^13.0.1",
"electron-packager": "^7.0.3",
"electron-reload": "^1.0.0",
"watchify": "^3.7.0"
}
}
npm run electron
安装插件:
npm install --save-dev electron-reloader
引入插件
热加载
main.js
const reloader = require('electron-reloader')
reloader(module)
运行package.json的main脚本的进程是主进程
每个Electron中的web页面运行在它的渲染进程的进程中
ctrl+shift+i打开渲染进程调试
或者
main.js
mianWindow.webContents.openDevTools()
打开调试工具
文档地址:
https://www.electronjs.org/zh/docs/latest/api/menu
main.js
const {app,BrowserWindow,Menu} = require('electron')
app.on('ready',()=>{
const mainWindow = new BrowserWindow({
width:600,
height:600,
webPreferences:{
nodeIntegration:true,
}
})
mainWindow.loadFile('./src/index.html')
//定义菜单模板
const template = [
{
label:'文件',
submenu:[
{
label:'新建项目'
}
]
},
{
label:'关于'
}
]
//编译模板
const menu = Menu.buildFromTemplate(template)
//设置菜单
Menu.setApplicationMenu(menu)
})
Menu.setApplicationMenu(menu)
定义点击事件
可以抽离出来
menu.js
const {BrowserWindow,Menu} = require('electron')
//定义菜单模板
const template = [
{
label:'文件',
submenu:[
{
label:'新建项目',
click(){
new BrowserWindow({
width:200,
height:200,
})
}
}
]
},
{
label:'关于'
}
]
//编译模板
const menu = Menu.buildFromTemplate(template)
//设置菜单
Menu.setApplicationMenu(menu)
main.js引入
require('./menu.js')
可以使用无边框
main.js
使用css样式自定义菜单div拖拽
main.js
const {app,BrowserWindow,Menu} = require('electron')
app.on('ready',()=>{
const mainWindow = new BrowserWindow({
width:600,
height:600,
frame:false,
webPreferences:{
nodeIntegration:true,
contextIsolation:false,
enableRemoteModule:true
},
})
require('@electron/remote/main').initialize()
require('@electron/remote/main').enable(mainWindow.webContents)
mainWindow.loadFile('./src/index.html')
menu.js
const {BrowserWindow,Menu} = require('electron')
//定义菜单模板
const template = [
{
label:'文件',
submenu:[
{
label:'新建项目',
click(){
new BrowserWindow({
width:200,
height:200,
})
}
}
]
},
{
label:'关于'
}
]
//编译模板
const menu = Menu.buildFromTemplate(template)
//设置菜单
Menu.setApplicationMenu(menu)
index,js
const {BrowserWindow} = require('@electron/remote')
const newWindow = document.querySelector('.new-window')
newWindow.onclick = function(){
new BrowserWindow({
width:200,
height: 200
})
}
index.html
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>Documenttitle>
<link rel="stylesheet" href="./index.css"/>
head>
<body>
<ul class="custom-menu">
<li class="new-window">新建li>
<li>关于li>
ul>
<h1>Helloh1>
<script src="./index.js">script>
body>
html>
index.css
* {
margin: 0;
padding: 0;
}
.custom-menu {
height: 80px;
width: 100%;
background: orange;
-webkit-app-region:drag;
}
ul {
list-style: none;
}
.custom-menu li{
float: left;
width: 60px;
line-height: 80px;
text-align: center;
margin-left: 20px;
-webkit-app-region: no-drag;
}
拖拽样式会影响弹出新窗口或者点击事件等功能
此时设置style为-webkit-app-region: no-drag;即可!!!
shell是两种进程都可用的模块
不需要通过remote
html中写a标签
index.js
const {shell} = require('electron')
const allA = document.querySelectorAll('a')
allA.forEach(item => {
item.onclick = function(e){
e.preventDefault()
//阻止默认行为
shell.openExternal(item.href)
}
})
<button onclick="openFile()" >打开文件button>
index.js
引入fs模块读取
const fs = require('fs')
打开文件
//打开文件
const textareaEl = document.querySelector('textarea')
function openFile(){
const res = dialog.showOpenDialogSync({
title:'读取文件',
buttonLabel:'读取',
filters: [
{ name: 'Custom File Type', extensions: ['js'] },
{ name: 'All Files', extensions: ['*'] }
]
})
console.log(res[0])
const fileContent = fs.readFileSync(res[0]).toString()
console.log(fileContent)
textareaEl.value = fileContent
}
<button onclick="saveFile()" >保存文件button>
<textarea id="tex2">textarea>
保存文件!!!
//打开文件
const textareaEl2 = document.querySelector('#tex2')
//保存文件
function saveFile(){
//返回值是路径
const res = dialog.showSaveDialogSync({
title:'保存文件',
buttonLabel:'保存',
filters: [
{ name: 'Custom File Type', extensions: ['ts'] },
{ name: 'All Files', extensions: ['*'] }
]
})
//通过node写文件
fs.writeFileSync(res,textareaEl2.value)
}
导入模块globalShortcut定义快捷键
const {app,BrowserWindow,globalShortcut} = require('electron')
注册快捷键
模块使用:
globalShortcut.register('CommandOrcontrol+X',()=>{
console.log("按下了ctrl+x");
})
globalShortcut.register('CommandOrcontrol+M',()=>{
mainWindow.maximize()
})
globalShortcut.register('CommandOrcontrol+T',()=>{
mainWindow.unmaximize()
})
globalShortcut.register('CommandOrcontrol+H',()=>{
mainWindow.close()
})
完整代码:
app.on('ready',()=>{
const mainWindow = new BrowserWindow({
width:600,
height:600,
// frame:false,
webPreferences:{
nodeIntegration:true,
contextIsolation:false,
enableRemoteModule:true
},
})
require('@electron/remote/main').initialize()
require('@electron/remote/main').enable(mainWindow.webContents)
mainWindow.loadFile('./src/index.html')
//定义菜单模板
require('./menu.js')
mainWindow.webContents.openDevTools()
globalShortcut.register('CommandOrcontrol+X',()=>{
console.log("按下了ctrl+x");
})
globalShortcut.register('CommandOrcontrol+M',()=>{
mainWindow.maximize()
//最大化
})
globalShortcut.register('CommandOrcontrol+T',()=>{
mainWindow.unmaximize()
//恢复正常
})
globalShortcut.register('CommandOrcontrol+H',()=>{
mainWindow.close()
})
})
和主进程相似
const {BrowserWindow,dialog,globalShortcut} = require('@electron/remote')
定义一个点击事件
渲染进程发送给主进程
const {shell,ipcRenderer} = require('electron')
const maxwindow = function(){
console.log("窗口最大化")
ipcRenderer.send('max-window')
}
主进程接收const {shell,ipcRenderer} = require(‘electron’):
const {app,BrowserWindow,globalShortcut, ipcMain} = require('electron')
//定义自定义事件
ipcMain.on('max-window',()=>{
mainWindow.maximize()
})
通讯传参
index.js
let windowSize = 'unmax-window'
const maxwindow = function(){
windowSize = windowSize == 'max-window'?'unmax-window':'max-window'
ipcRenderer.send('max-window',windowSize)
}
主进程获取数据
//定义自定义事件
ipcMain.on('max-window',(event,arg)=>{
if(arg === 'max-window'){
return mainWindow.maximize()
}else{
return mainWindow.unmaximize()
}
})
使用electron-packager (十分不推荐)
npm install [email protected] -g
npm install electron-packager --save-dev
测试失败,不推荐使用此方式
package.json文件更改
"package": "electron-packager ./ DemoApps --overwrite --app-version=1.0.0 --platform=win32 --arch=all --out=../DemoApps --version=1.2.1 --icon=./public/img/app-icon.icns"
此时
npm run package
即可打包
使用electron-builder(推荐)
npm install electron-builder
修改package.json文件
增加字段
"build": {
"appId": "com.fuck.app",
"productName":"软件名",
"win": {
"icon": "./icon.ico",
"target": [
"nsis"
]
},
"nsis": {
"oneClick": false,
"perMachine": true,
"allowToChangeInstallationDirectory": true
}
},
"electronDownload":{
"mirror":"https://npm.taobao.org/mirrors/electron/"
//配置下载加速镜像
},
"scripts"内增加运行脚本
"build": "electron-builder"
打包成功!!
"build": {
"productName":"xxxx",//项目名 这也是生成的exe文件的前缀名
"appId": "com.leon.xxxxx",//包名
"copyright":"xxxx",//版权 信息
"directories": { // 输出文件夹
"output": "build"
},
"nsis": {
"oneClick": false, // 是否一键安装
"allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
"allowToChangeInstallationDirectory": true, // 允许修改安装目录
"installerIcon": "./build/icons/aaa.ico",// 安装图标
"uninstallerIcon": "./build/icons/bbb.ico",//卸载图标
"installerHeaderIcon": "./build/icons/aaa.ico", // 安装时头部图标
"createDesktopShortcut": true, // 创建桌面图标
"createStartMenuShortcut": true,// 创建开始菜单图标
"shortcutName": "xxxx", // 图标名称
"include": "build/script/installer.nsh", // 包含的自定义nsis脚本
},
"publish": [
{
"provider": "generic", // 服务器提供商 也可以是GitHub等等
"url": "http://xxxxx/" // 服务器地址
}
],
"files": [
"dist/electron/**/*"
],
"dmg": {
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
]
},
"mac": {
"icon": "build/icons/icon.icns"
},
"win": {
"icon": "build/icons/aims.ico",
"target": [
{
"target": "nsis",
"arch": [
"ia32"
]
}
]
},
"linux": {
"icon": "build/icons"
}
}
我测试的完整pachage.json
{
"name": "ele",
"version": "1.0.0",
"description": "electron-demo",
"main": "main.js",
"dependencies": {
"@electron/remote": "^2.0.8",
"electron-reloader": "^1.2.3",
"npm": "^8.5.4"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"electron": "electron .",
"watch": "watchify app/appEntry.js -t babelify -o public/js/bundle.js --debug --verbose",
"build": "electron-builder"
},
"build": {
"appId": "com.fuck.app",
"productName":"软件名",
"win": {
"icon": "./icon.ico",
"target": [
"nsis"
]
},
"nsis": {
"oneClick": false,
"perMachine": true,
"allowToChangeInstallationDirectory": true
}
},
"electronDownload":{
"mirror":"https://npm.taobao.org/mirrors/electron/"
},
"devDependencies": {
"babel": "^6.5.2",
"babel-plugin-transform-es2015-spread": "^6.8.0",
"babel-plugin-transform-object-rest-spread": "^6.8.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.5.0",
"babelify": "^7.3.0",
"browserify": "^13.0.1",
"electron-builder": "^22.14.13",
"electron-packager": "^7.7.0",
"electron-reload": "^1.0.0",
"watchify": "^3.7.0"
},
"keywords": [],
"author": "",
"license": "ISC"
}
图标问题
使用png或者jpg文件做图标
1、打包后图标未显示或者错误
打包后,会在打包目录中生成.icon-ico
文件夹
文件夹内会生成我们要使用的图标文件icon.ico
生成后替换配置我们在目录中的jpg或者ico等文件。
重新打包即可。
2、测试图标正常但是打包后运行的图标显示错误
可能是图标路径配置不正确使用以下绝对路径方式配置!
main.js
此时再打包即可
创建vue项目
安装electron
加运行脚本: "electron": "electron .",
加"main": "main.js",
并写一个main.js
正常写
加载vue项目的url
mainWindow.loadURL('http://localhost:8080/#/')
即可完成!
上线时将vue打包的index.html引入!
项目地址:
github:https://github.com/simulatedgreg/electron-vue
npm install -g vue-cli
npm i -g @vue/cli-init
vue init simulatedgreg/electron-vue 项目名