总结
主要执行以下命令
全局安装electron:npm install electron -g
安装electron-builder依赖:vue add electron-builder
运行桌面程序:npm run electron:serve
打包应用程序:npm run electron:build
更新应用程序:npm i electron-updater --save
electron-builder 教程
一、本人比较笨,拷贝原始项目后,安转依赖并启动
执行命令:npm install
执行命令:npm run serve
二、全局安装electron:
执行命令:npm install electron -g
三、安装electron-builder依赖:
执行命令:vue add electron-builder
electron-builder安装成功后项目目录如下:

会发现目录里多了一个background.js 的文件,并且package.json 里多了依赖和执行命令其中这个“main”: “background.js” 是electron的入口文件
四、运行桌面程序
执行命令:npm run electron:serve
执行以上命令后项目启动速度较慢,可以注释掉background.js文件中await installExtension(VUEJS_DEVTOOLS) 这一句代码

项目运行后显示界面如下:

五、打包
执行命令:npm run electron:build
执行打包命令后报错:"directories" in the root is deprecated, please specify in the "build",如下图显示:

解决办法,删掉“directories”这部分内容:

打包成功后exe程序所在位置:
根目录/dist_electron/win-unpacked/vue-antd-pro.exe ,如下图所示:

六、在vue.config.js中module.exports中添加pluginOptions配置:更换exe应用程序中的名称和图标
打包教程地址:https://blog.csdn.net/Assassin_EZI0/article/details/107144377

执行打包命令:npm run electron:build,重新打包后

七、更新应用程序
客户安装应用以后,如果有新功能更新,那客户那边如何更新?解决方案,安装:electron-updater
执行命令:npm i electron-updater --save
介绍一下原理:使用electron-updater, 打包后会生成一个latest.yml 的文件,里面包含了版本号等描述信息,
并且electron-updater 提供了一系列监听事件,允许应用向服务器检测当前版本是否可以更新,
如果可以更新,在对应的监听事件里做了相关处理(下载最新版本,下载完成后退出并重新安装)
在目录下新增一个目录_main, 里面有两个文件,events.js(定义了事件名称) 和 updater.js (处理接收)
events.js:
// ipc通信事件, main 和 render都会用
export default {
downLoadUpdate: 'downLoadUpdate', // 手动下载更新
checkUpdate: 'checkUpdate', // 请求检查更新
startCheckUpdate: 'startCheckUpdate', // 开始检查更新
checkUpdateError: 'checkUpdateError', // 检查更新出错
checkingUpdate: 'checkingUpdate', // 正在检查更新
updateAvailable: 'updateAvailable', // 有新版本更新
updateNotAvailable: 'updateNotAvailable', // 没有新版本更新
updateDownloading: 'updateDownloading', // 正在下载中
updateDownloaded: 'updateDownloaded' // 下载完成
}
updater.js:
import { autoUpdater } from 'electron-updater'
import { ipcMain } from 'electron'
import Events from '@/__main/events'
// 主进程接收渲染进程(页面)派发过来的 检测更新事件
ipcMain.on(Events.checkUpdate, () => {
// 向服务端查询现在是否有可用的更新。在调用这个方法之前,必须要先调用 setFeedURL
autoUpdater.checkForUpdates()
})
// 主进程接收渲染进程(页面)派发过来的 下载更新事件
ipcMain.on(Events.downLoadUpdate, () => {
autoUpdater.downloadUpdate()
})
export function listenUpdater(mainWindow, feedUrl) {
autoUpdater.autoDownload = false
autoUpdater.setFeedURL(feedUrl)
// 当更新发生错误的时候触发
autoUpdater.on('error', function(error) {
mainWindow.webContents.send(Events.checkUpdateError, JSON.stringify(error))
})
// 当开始检查更新的时候触发
autoUpdater.on('checking-for-update', function() {
mainWindow.webContents.send(Events.checkingUpdate)
})
// 当发现一个可用更新的时候触发,更新包下载会自动开始
autoUpdater.on('update-available', function(info) {
mainWindow.webContents.send(Events.updateAvailable, info)
})
// 当没有可用更新的时候触发
autoUpdater.on('update-not-available', function(info) {
mainWindow.webContents.send(Events.updateNotAvailable, info)
})
// 更新下载进度事件
autoUpdater.on('download-progress', function(progressObj) {
mainWindow.webContents.send(Events.updateDownloading, progressObj)
})
// 下载完成
autoUpdater.on('update-downloaded', function() {
mainWindow.webContents.send(Events.updateDownloaded)
autoUpdater.quitAndInstall()
})
}
在background.js 里执行监听

每次更新时只需把exe文件和 latest.yml 文件放到服务器上就行了!
八:自定义electron窗口导航栏
方法一:自定义electron窗口
1、在background.js文件中找到BrowserWindow中设置frame为false,关闭原生导航栏

2、在App.vue中引入窗口组件mainHeader.vue

3、mainHeader.vue代码如下
<template>
<div id="app">
<div class="titleBar">
<div class="title">
<div class="logo">
<img src="@/assets/logo.webp">
</div>
<div class="txt">窗口标题</div>
</div>
<div class="windowTool">
<div @click="minisize">
<i class="iconfont iconminisize"></i>
</div>
<div v-if="!isMaxSize" @click="restore">
<i class="iconfont iconrestore"></i>
</div>
<div v-else @click="maxsize">
<i class="iconfont iconmaxsize"></i>
</div>
<div @click="close" class="close">
<i class="iconfont iconclose"></i>
</div>
</div>
</div>
<div id="nav">
<router-link to="/about">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
<script>
const {remote}=window.require('electron')
export default {
data(){
return{isMaxSize:true}
},
methods:{
//最小化
minisize(){
var win=remote.getCurrentWindow()
win.minimize()
},
//恢复
restore(){
remote.getCurrentWindow().restore()
this.isMaxSize=!this.isMaxSize
},
//最大化
maxsize(){
console.log(remote.getCurrentWindow())
var win=remote.getCurrentWindow()
win.maximize()
this.isMaxSize=!this.isMaxSize
},
//关闭
close(){
remote.getCurrentWindow().hide()
}
},
}
</script>
<style>
@import url(https://at.alicdn.com/t/font_1378132_s4e44adve5.css);
.titleBar{
height:38px;
line-height: 36px;
background: #fff1f0;
display: flex;
border-bottom: 1px solid #f5222d;
}
.title{flex:1;
display: flex;
-webkit-app-region:drag;
}
.logo{padding-left:8px;
padding-right:6px;
}
.logo img{
width:20px;
height:20px;
margin-top:7px;
}
.txt{text-align: left;
flex:1;
}
.close:hover{color: #fff;
background-color:#ff4d4f;
}
.windowTool div{
color:#888;
height:100%;
width:38px;
display: inline-block;
cursor:pointer;
}
i{font-size:12px;}
.windowTool div:hover{background: #ffccc7;}
body{margin:0;
padding:0;
overflow: hidden;
height:100%;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
display: flex;
flex-direction: column;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
注意:使用上述代码方法时需要注意在background.js文件中找到BrowserWindow将enableRemoteModule设置为true

方法二:Electron自定义导航栏
1、在主进程background.js文件中配置frame: false 关闭原生导航栏

2、在App.vue中引入窗口组件mainHeader.vue

3、mainHeader.vue代码如下
<template>
<section class="MainHeader">
<div style="display: flex;">
<router-link :to="'/timetables'" class="logo noDrag" v-stat="{action:'logo'}"/>
<div class="userInfo noDrag" v-if="userInfo">
<div class="name " @click="path" v-stat="{action:'userInfo'}">
<img src="~assets/images/user.webp"/>
<span>{{userInfo?userInfo.name:''}}</span>
</div>
<span class="logout" @click="logOut">退出</span>
</div>
</div>
<div class="systemBtn">
<i class="mini noDrag" title="最小化" @click="setWin('min')"></i>
<i title="最大化" class="max noDrag" @click="setWin('max')"></i>
<i title="关闭" class="close noDrag" @click="setWin('close')"></i>
</div>
</section>
</template>
<script>
/**渲染进程(也就是当前页面)通过ipcRenderer.send 将方法字段名传递给主进程。**/
const {ipcRenderer} = window.require("electron");
export default {
methods: {
setWin(type){
ipcRenderer.send(type);
}
}
</script>
<style>
/**自定义的导航栏鼠标点击是无法拖动的,需要在css中增加-webkit-app-region: drag; 让鼠标可以拖动,若可拖动的html结构中有点击事件,那//需要在点击元素的css中另加-webkit-app-region: no-drag; 让其可触发点击事件,若不加该css则点击事件无效。**/
.MainHeader {
-webkit-app-region: drag;
.noDrag{
-webkit-app-region: no-drag;
}
}
</style>
4、在主进程background.js中执行ipcMain方法。
import {BrowserWindow, ipcMain} from 'electron'
mainWindow = new BrowserWindow({
height: 690,
useContentSize: true,
width: 1100,
minWidth: 1100,
minHeight: 690,
frame: false
})
ipcMain.on('min', () => mainWindow.minimize());
ipcMain.on('max', () => {
if (mainWindow.isMaximized()) {
mainWindow.restore();
} else {
mainWindow.maximize()
}
});
ipcMain.on('close', () => mainWindow.close());

九:自定义桌面应用程序后,浏览器端无法识别window,客户端无法启动,因此可以检查代码是否正在Electron或浏览器中执行,来判断是否引用window.require('electron')
export function isElectron() {
// Renderer process
if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') {
return true;
}
// Main process
if (typeof process !== 'undefined' && typeof process.versions === 'object' && !!process.versions.electron) {
return true;
}
// Detect the user agent when the `nodeIntegration` option is set to true
if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) {
return true;
}
return false;
}
在mainHeader组件中引入
import {isElectron} from '@/utils/isElectron'
if(isElectron()){//检查代码是否正在Electron或浏览器中执行 var {remote}=window.require('electron') console.log("Electron中执行 !");}else{ console.log("浏览器中执行");}
如图所示:

上一篇:没有了
下一篇:没有了