前言
小浪学习electron
的原因是软件构造课需要交一个软件作业,不想用java
写,还不能是网页,一开始想到的是用uniapp
写个项目打包成APP
,然后想了想,一直听说 electron
可以把前端页面(原生
/h5
/vue
/react
...)打包成桌面应用,把前端页面当做GUI
这岂不是很Nice
,Typora
就是 electron
做的,很好奇,就去学学看,下面是小浪学习 electron
的笔记,希望能给大家一点帮助,学习 electron
教程好像很多,但是还是官方文档比较清晰全面,有可能你在视频教程里看见的能使用的,自己去敲的时候发现各种问题,还以为是自己哪里拼错了,一看是官方文档更新了...
1.基础使用
要想弄个桌面端的应用,那我们得快速的去了解它
1.1终端乱码问题
tip
: electron 控制打印会出现中文乱码
只需要在终端(cmd
)输入 chcp 65001
运行下就行了
1.2安装
// 如果没有node 的话先装 node
http://nodejs.cn/download/
// 在当前目录安装最新
npm i -D electron
// 全局安装最新
cnpm install electron -g
// 当然你可以指定版本号安装
npm i -D electron@11.0.4
node -v
electron -v
查看是否安装成功
1.3快速创建
开始创建一个 electron
- 首先说下目录必须包括:
package.json
这个文件 - 然后要有个入口文件下面这个例子我用
index.js
举例,不过一般写成main.js
比较好 - 起码你需要个展示的GUI界面,一般是前端页面,也可以直接放个网址
新建一个目录(项目):
初始化package.json
文件
npm init
描述记得写,这个electron
打包的时候我记得需要描述
启动命令写 "test": "nodemon --watch index.js --exec electron ."
,这样子最后在终端输入 npm test
这样每次修改index.js
主进程文件都会重新启动项目了,index.js
可以自行修改 main.js
等等
来看看最后的的 package.json
文件吧
// package.json 文件
{
"name": "electron_demo",
"version": "1.0.0",
"description": "\"这是一个electron demo\"",
"main": "index.js",
"scripts": {
"test": "nodemon --watch index.js --exec electron ."
},
"author": "",
"license": "ISC"
}
我的目录下放了以下几个文件
electron
分为两个进程 主进程 和 渲染进程
index.js
这个文件是 主进程
官方是这样写的
const { app, BrowserWindow } = require('electron')
function createWindow () {
// 创建浏览器窗口
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// 并且为你的应用加载index.html
win.loadFile('index.html')
// 打开开发者工具
win.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
// 否则绝大部分应用及其菜单栏会保持激活。
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// 在macOS上,当单击dock图标并且没有其他窗口打开时,
// 通常在应用程序中重新创建一个窗口。
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. 也可以拆分成几个文件,然后用 require 导入。
我看其他人差不多是这样写的
const { app, BrowserWindow } = require('electron')
let win
// 监听electron 加载完毕的时候的创建窗口等等
app.on('ready', function () {
// 创建一个窗口 设置属性
win = new BrowserWindow({
//fullscreen: true //全屏
//frame: false, //让桌面应用没有边框,这样菜单栏也会消失
resizable: false, //不允许用户改变窗口大小
width: 800, //设置窗口宽高
height: 600,
icon: iconPath, //应用运行时的标题栏图标
minWidth: 300, // 最小宽度
minHeight: 500, // 最小高度
maxWidth: 300, // 最大宽度
maxHeight: 600, // 最大高度
// 进行对首选项的设置
webPreferences:{
backgroundThrottling: false, //设置应用在后台正常运行
nodeIntegration:true, //设置能在页面使用nodejs的API
contextIsolation: false, //关闭警告信息
//preload: path.join(__dirname, './preload.js')
}
})
// 这里让主进程加载一个index.html
win.loadFile('index.html')
// 设置为最顶层
//win.setAlwaysOnTop(true)
//win.loadURL(`www.baidu.com`) 可以让主进程打开文件或者一个链接
// 监听窗口关闭事件
win.on('closed',()=>{
//释放win
win = null
})
})
// 监听所有的窗口都关闭了
app.on('window-all-closed', () => {
console.log('窗口全部都关闭了')
})
index.html
是渲染进程也就是前端页面里面随便写点东西,这里相当是把前端当成 GUI 了
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>electron test</title>
</head>
<body>
electron demo
<script></script>
</body>
</html>
这样使用
npm test
就可以出来这么一个界面了,test
这个命令 是package.json
script
中配的
2.Remote 模块
在渲染进程里(比如index.html
里面加载了一些js文件,那里面的js如果要使用到 BrowserWindow 这些属性的话就必须使用 remote
)
使用 remote
模块, 你可以调用 main
进程对象的方法
2.1.electron14.0之前版本使用
在主进程的窗口中加入
enableRemoteModule: true
参数才能够调用remote模块
const { app, BrowserWindow } = require('electron')
app.on('ready', function () {
let win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
//这里进行加入
enableRemoteModule: true,
nodeIntegration: true,
contextIsolation: false,
},
})
win.loadFile('index.html')
// 监听所有的窗口都关闭了
app.on('window-all-closed', () => {
//释放win
win = null
console.log('窗口全部都关闭了')
})
})
然后在渲染进程里写,这里我直接内嵌js了
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>electron test</title>
</head>
<body>
electron demo
<button id="btn">添加新的窗口</button>
<script>
const { log } = console
// 导入 remote 中的 BrowserWindow
const { BrowserWindow } = require('electron').remote
const btn = document.getElementById('btn')
btn.onclick = () => {
let newWin = new BrowserWindow({
width: 800,
height: 600,
})
// newWin.loadURL('www.baidu.com')
win.loadFile('index2.html')
newWin.on('close', () => {
newWin = null
})
}
</script>
</body>
</html>
这里点击按钮,就又可以创建一个新的窗口了
2.2.electron14.0版本API修改
但是这里是有版本的区分的,这里一开始也困扰了我很久很久...最后看了下文档
14.0
后 改了,我用的15
。。。
1.还得自行安装
remote
npm i -D @electron/remote
2.主进程中导入
app.on('ready',function(){
require('@electron/remote/main').initialize()
})
3.渲染进程中
//这样来引入remote
const { BrowserWindow } = require('@electron/remote')
3.创建系统菜单
1.新建一个 menu.js
// 1.导入 electron 中的 Menu
const { Menu } = require('electron')
// 2.创建菜单模板,数组里的每一个对象都是一个菜单
const template = [
{
label: '菜单一',
// submenu 代表下一级菜单
submenu: [
{
label: '子菜单一' ,
// 添加快捷键
accelerator: 'ctrl+n'
},
{ label: '子菜单二' },
{ label: '子菜单三' },
{ label: '子菜单四' },
],
},
{
label: '菜单二',
// submenu 代表下一级菜单
submenu: [
{ label: '子菜单一' },
{ label: '子菜单二' },
{ label: '子菜单三' },
{ label: '子菜单四' },
],
},
]
// 3.从模板中创建菜单
const myMenu = Menu.buildFromTemplate(template)
// 4.设置为应用程序菜单
Menu.setApplicationMenu(myMenu)
accelerator: 'ctrl+n'
可以指定菜单的快捷键
2.随便写个页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>自定义菜单</title>
</head>
<body>
自定义菜单
<script></script>
</body>
</html>
3.写 main.js
// 1.引入 electron
const { app, BrowserWindow } = require('electron')
// 定义一个窗口
let win = null
// 2.引入自定义的菜单
require('./menu')
// 3.监听ready
app.on('ready', function () {
win = new BrowserWindow({
width: 800,
height: 600,
})
// 打开控制台
win.webContents.openDevTools()
win.loadFile('./index.html')
// 4.监听窗口关闭事件
win.on('close', () => {
win = null
})
})
npm test启动
4.给菜单添加事件
比如给子菜单添加一个点击事件新建一个窗口
// 1.导入 electron 中的 Menu
const { Menu, BrowserWindow } = require('electron')
// 2.创建菜单模板,数组里的每一个对象都是一个菜单
const template = [
{
label: '菜单一',
// submenu 代表下一级菜单
submenu: [
{
label: '子菜单一',
// 添加点击事件
click: () => {
// 创建一个新的窗口
let sonWin = new BrowserWindow({
width: 200,
height: 200,
})
sonWin.loadFile('./index2.html')
// 为关闭的时候进行清空
sonWin.on('close', () => {
sonWin = null
})
},
},
{ label: '子菜单二' },
{ label: '子菜单三' },
{ label: '子菜单四' },
],
},
{
label: '菜单二',
// submenu 代表下一级菜单
submenu: [
{ label: '子菜单一' },
{ label: '子菜单二' },
{ label: '子菜单三' },
{ label: '子菜单四' },
],
},
]
// 3.从模板中创建菜单
const myMenu = Menu.buildFromTemplate(template)
// 4.设置为应用程序菜单
Menu.setApplicationMenu(myMenu)
效果图
上面的的开发者工具和chrome/edge浏览器一样,在菜单栏的
View -> Toggle Developer Tools
,或者Ctrl + Shift + I
就能调用出来,用来调试页面
5.使用Node.js 模块/API
比如写个读写文件例子
在主线程创建窗口的时候 webPreferences
一定在加上 nodeIntegration: true
,contextIsolation: false
这样在渲染进程才能使用node
的一些语法
main.js
// 导入 electron
const { app, BrowserWindow } = require('electron')
let mainWindow = null
app.on('ready', () => {
// // 新建一个窗口
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true, // 是否集成 Nodejs,把之前预加载的js去了,发现也可以运行
contextIsolation: false,
},
})
// 加载渲染文件
mainWindow.loadFile('./main.html')
// 窗口关闭后清空变量
mainWindow.on('close', () => {
mainWindow = null
})
})
main.html 主要的渲染文件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>读写文件测试</title>
</head>
<body>
<button onclick="readFile()">读取文件</button>
<button onclick="writeFile()">写入文件</button>
<p id="show_file_content">页面内容</p>
<script src="./index.js"></script>
</body>
</html>
index.js 加载需要的js
可以看出,在渲染进程中,就是main.html
里面加载的 index.js
中,既可以使用 docment.getElementById
这些 WebAPI
,又能使用用 node
的模块进行混写
// 导入 node 的模块
const fs = require('fs')
const path = require('path')
const { log } = console
// 获取到文件展示的dom
const showContent = document.getElementById('show_file_content')
// 读取文件
function readFile() {
console.log('读取文件')
fs.readFile(path.join(__dirname, '/test.txt'), (err, data) => {
if (err) {
throw new Error(err, '读取文件失败')
}
showContent.innerText = data
})
}
// 需要写入的内容
const content = '今天是国庆的第二天,在学 electron'
// 写入文件
function writeFile() {
fs.writeFile(
path.join(__dirname, '/test.txt'),
content,
'utf8',
(err, data) => {
if (err) {
return new Error(err, '读取文件失败')
}
log('写入文件成功')
}
)
}
测试用的 txt
今天是国庆的第二天,在学 electron
项目的目录
效果图
6.设置无边框
在创建窗口的时候 可以设置无边框,带的菜单也消失了
let win = new BrowserWindow({
frame: false, //让桌面应用没有边框,这样菜单栏也会消失
width: 800, //设置窗口宽高
height: 600,
})
菜单其实它还在,你仍然可以通过快捷键调用出菜单,可以直接删除菜单win.removeMenu()
没有菜单栏怎么去拖拽窗口
在css中你可以设置哪个可以进行拖拽/禁止拖拽
比如 body{ -webkit-app-region: drag | no-drag;}
效果图:无边框,在
body
设置可拖拽
7.系统托盘
看到上面这个图大家都应该清楚吧,当我们关闭一个应用程序的时候,它其实关闭了,但是没有完全关闭,只是隐藏了,有的就存在系统托盘中,那么如何在electron
设置系统托盘呢
主进程 index.js
在electron
这里一开始我就添加系统托盘,当然你可以监听窗口被关闭的时候在创建托盘
// 引入托盘 Tray,和 Menu 等下要创建菜单,nativeImage创建 icon图标
const { app, BrowserWindow, Tray, Menu, nativeImage } = require('electron')
const path = require('path')
let win, tray
app.on('ready', function () {
win = new BrowserWindow({
width: 800,
height: 600,
})
// 创建icon我这里使用的是一个png
const icon = nativeImage.createFromPath(
path.join(__dirname, '/static/icon.png')
)
// 实例化一个 托盘对象,传入的是托盘的图标
tray = new Tray(icon)
// 移动到托盘上的提示
tray.setToolTip('electron demo is running')
// 还可以设置 titlle
tray.setTitle('electron demo')
// 监听托盘右键事件
tray.on('right-click', () => {
// 右键菜单模板
const tempate = [
{
label: '无操作',
},
{
label: '退出',
click: () => app.quit(),
},
]
//通过 Menu 创建菜单
const menuConfig = Menu.buildFromTemplate(tempate)
// 让我们的写的托盘右键的菜单替代原来的
tray.popUpContextMenu(menuConfig)
})
//监听点击托盘的事件
tray.on('click', () => {
// 这里来控制窗口的显示和隐藏
if (win.isVisible()) {
win.hide()
} else {
win.show()
}
})
win.loadFile('index.html')
})
// 监听所有的窗口都关闭了
app.on('window-all-closed', () => {
//释放win
win = null
console.log('窗口全部都关闭了')
})
效果图
8.进程间通信
electron
中主进程和渲染进程两者之间需要通信
官方文档:
主线程 到 渲染线程 通过 webContents.send
来发送 --->ipcRenderer.on
来监听
渲染线程 到 主线程 需要通过 ipcRenderer.send
发送 ---> ipcMain.on
来监听
8.1.主进程到渲染进程
webContents.send(channel, ...args)
channel
String...args
any[]
主进程
mian.js
在主进程中使用 webContents.send
发送消息
//主进程
const { app, BrowserWindow } = require('electron')
let win
// 监听electron 加载完毕的时候的创建窗口等等
app.on('ready', function () {
// 创建一个窗口
win = new BrowserWindow({
width: 800, //设置窗口宽高
height: 600,
// 进行对首选项的设置
webPreferences: {
enableRemoteModule: true,
nodeIntegration: true, //设置能在页面使用nodejs的API
contextIsolation: false, //关闭警告信息
},
})
// 发送给渲染线程
setTimeout(() => {
win.webContents.send('mainMsg', '我是主线程发送的消息')
}, 3000)
// 这里让主进程加载一个main.html
win.loadFile('main.html')
})
// 监听所有的窗口都关闭了
app.on('window-all-closed', () => {
//释放win
win = null
app.quit()
console.log('窗口全部都关闭了')
})
渲染进程
main.html
外链一个render.js
在渲染线程中使用 ipcRenderer.on
来进行监听
ipcRenderer.on(channel, listener)
channel
Stringlistener
Function
监听 channel
, 当有新消息到达,使用 listener(event, args...)
调用 listener
.
还有个监听一次的消息ipcRenderer.once(channel, listener)
为这个事件添加一个一次性 listener
函数.这个 listener
将在下一次有新消息被发送到 channel
的时候被请求调用,之后就被删除了
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>通信测试</title>
</head>
<body>
通信测试
<p id="receive">接收信息</p>
<script src="./render.js"></script>
</body>
</html>
//渲染进程
//引入ipcRenderer
const electron = require('electron')
const { ipcRenderer } = require('electron')
const { log } = console
log(ipcRenderer)
ipcRenderer.on('mainMsg', (event, task) => {
log(task)
document.getElementById('receive').innerText = task
})
效果图
8.2.渲染进程到主进程
render.js
渲染线程中进行发送ipcRenderer.send
ipcRenderer.send(channel[, arg1][, arg2][, ...])
channel
Stringarg
(可选)
还有发送同步消息的ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>通信测试</title>
</head>
<body>
通信测试
<p id="receive">接收信息</p>
<button onclick="sendMain()">发送消息给主线程</button>
<script src="./render.js"></script>
</body>
</html>
const electron = require('electron')
const { ipcRenderer } = require('electron')
//...
function sendMain() {
ipcRenderer.send('task', '退出程序')
}
main.js
主进程里面ipcMain.on
进行监听,这里退出程序
ipcMain.on(channel, listener)
channel
Stringlistener
Function
监听 channel
, 当新消息到达,将通过 listener(event, args...)
调用 listener
.
还有个 ipcMain.once(channel, listener)
为事件添加一个一次性用的listener
函数.这个 listener
只有在下次的消息到达 channel
时被请求调用,之后就被删除了.
const { app, BrowserWindow, ipcMain } = require('electron')
// 监听electron 加载完毕的时候的创建窗口等等
app.on('ready', function () {
//...
})
ipcMain.on('task', (event, info) => {
if (info === '退出程序') {
app.quit()
}
})
效果图
这样就方便里我做一些窗口交互,比如todoList
,到时间了右下角弹出一个新的窗口进行提醒
8.3渲染进程到渲染进程
ipcRenderer.sendTo(webContentsId, channel, ...args)
webContentsId
Numberchannel
String...args
any[]
通过 channel
发送消息到带有 webContentsId
的窗口.
前提是要知道对应的渲染进程的ID
当然也可以让主进程作为中转站,先发到主进程在到其他的渲染进程
9.Vue + Electron
那么 Vue
怎么使用 Electron
打包呢?毕竟学习这个初衷,就是把 Vue
项目变成一个桌面应用,前面讲的都是原生的方法,那么继续往下面看吧
9.1你需要有个Vue项目
如果手上没有,那么用 vue ui
创建一个Vue
项目/或者直接在命令行里用 vue create
创建
vue ui
相信大家都会,这里我就是简单用vue ui
的建一个,这里大家可以略过
默认打开一个8000端口的服务,一个可视化的UI界面就出来了
选择左下角 更多--->项目管理器
创建
选择好目录后在此创建
填写一些基本信息,包管理我这里用 npm ,然后下一步
选择预设,我这里选手动
需要哪些插件选哪些,我这里就默认了,因为是个简单的例子
选择 Vue 的版本2.x 还是 3这些按照你的习惯来,平时写什么选什么,下面的选项我选择的标准
创建项目
我这里就不保存预设了,然后就是漫长的等待
创建完毕后运行改项目
启动项目
就会得到一个这样的默认页面
好了创建项目完毕,继续
9.2添加 electron
插件
在插件-->添加插件 搜索
vue-cli-plugin-electron-builder
,安装第一个
我这里默认选择electorn 13.0.0版本
安装完成后会出现在已安装插件里面
当然也可以在 命令行中进行安装
vue add electron-builder
9.3运行
在当前vue项目下的命令行输入下面的命令运行
npm run electron:serve
很好,已经运行出来了
9.4 package.json
background.js
查看package.json
文件找找主进程文件在哪
主进程文件是
background.js
,这个文件在Vue项目/src/下面
'use strict'
import { app, protocol, BrowserWindow } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
async function createWindow() {
// Create the browser window.
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
}
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
看到上面的主进程文件是不是很熟悉,你可以像以前一样做一些操作,使用node混写完成一些功能
9.5打包
上面我们只是运行出来了,上交的软件,老师总不会还特意去配环境,然后npm run electron:serve
吧,显然是不可能的,那我们继续进行打包成一个可执行的文件exe
命令行执行下面的命令
npm run electron:build
打包出现的问题
我在打包的时候特别不顺利... 查来查去原来
electron
是有问题
我给出的建议就是 把node_modules
目录下的 electron 删除
用cnpm
安装 electron
如果没有 cnpm
先进行安装
全局安装
cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 查看是否安装成功了
cnpm -v
重新安装
electron
cnpm i electron
打包
npm run electron:build
打包完成,打包的文件就放在项目下的 dist_electron
里面
9.6安装
双击就自动安装了
桌面上就出现这么一个应用图标
9.7自定义
点进去查看没有问题,但是是不是太low 了,一点击就是自动安装,而且使用的默认图标
安装打包工具
cnpm i electron-builder --D
9.7.1.首先找一个 icon
图片
好像有插件可以把图片转为各种大小的icon
安装下,这样就不用网站上转图片了
cnpm i electron-icon-builder
需要在package.json
中scripts
添加build-icon
指令
longzhu.jpg
这个图片自己找的 卡卡罗特 可以自行修改
output
是输出文件夹
"scripts": {
"build-icon": "electron-icon-builder --input=./public/longzhu.jpg --output=build --flatten"
},
命令行输入
npm run build-icon
build完成之后,生成了不同大小的图片
9.7.2.vue.config.js
因为我们之前安装的插件是 vue-cli-plugin-electron-builder
,而不是electron-builder
electron-builder
打包普通项目,build
配置直接在package.json
里面写
vue-cli-plugin-electron-builder
的 build
配置是需要在 项目根目录下 vue.config.js
里面配置
如果没有请新建
module.exports = {
pluginOptions: {
electronBuilder: {
builderOptions: {
appId: "com.test.app",
productName: "Lang", //项目名,也是生成的安装文件名,即aDemo.exe
copyright: "Copyright © 2021", //版权信息
directories: {
output: "./dist" //输出文件路径
},
win: {
//win相关配置
icon: "./build/icons/icon.ico", //图标,当前图标在根目录下,注意这里有两个坑
target: [
{
target: "nsis", //利用nsis制作安装程序,打包文件的后缀为exe
arch: [
"x64", //64位
"ia32" //32位
]
}
]
},
nsis: {
oneClick: false, //一键安装
language: "2052", //安装语言
perMachine: true, //应用所有用户
allowToChangeInstallationDirectory: true //用户可以选择路径
}
}
}
}
};
9.7.3.执行打包
npm run electron:build
OK,打包成功!
可能遇到的问题
打包的路上不是一帆风顺的,在这一步打包失败了,因为打包的时候去下载一些依赖,然后下载失败了
解决方法1:梯子
解决方法2: 可以参考这个
打包好的东西
打包好的东西放在我们之前配置的build
output: "./dist"
//输出文件路径
可以看出图标变了
我们可以自定义安装文件夹了
好了,基础的打包工作就这么结束了,大家可以自己写属于自己的软件,这里只是一个简单的应用教学
结语
Electron
真的不错诶,建议大家学习的时候多看看官方的文档,虽然官方文档还有很多地方没有翻译完整,但是并不影响我们去学习他的热情,感觉版本迭代很快,官方文档显得又多又乱,大家可以在文档上面搜索
往期精彩