1. 创建electron-vue
安装vue-cli 在安装后使用使命
// 项目的名字(不能有大写字母)
// 使用vue命令创建 electron-vue 项目
vue init simulatedgreg/electron-vue 项目名称
复制代码
例子:
- sass需要的输入y
- 下面axios、vue-electron、vue-router、vuex、vuex-electron这五项有不需要的就把光标移动到那一项,按空格
- 键就会把 * 去掉。我这里没有安装后两项。然后按回车键接着进行下面的步骤。
- 这里的ESLintwo和Karma+Mocha还有Spectron+Mocha我都没有安装,需要安装的写y(ESLint最好别安装要不然会让你很痛苦)
创建成功界面:
- 项目创建完成后请用以下命令:
// cd 到对应项目目录 如下:
cd electorn-vue-demo
// 查看目录中是否有安装好的插件,如没有请用以下命令安装(请务必安装 yarn) 关系到你项目能否正常启动:
yarn 处始化项目
复制代码
当我们打开package.json 可以以下这些命令
"build": "node .electron-vue/build.js && electron-builder",
"build:dir": "node .electron-vue/build.js && electron-builder --dir",
"build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
"build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
"dev": "node .electron-vue/dev-runner.js",
"pack": "npm run pack:main && npm run pack:renderer",
"pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
"pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
"postinstall": ""
复制代码
运行项目: yarn dev
就可以了,打包用 yarn build
到这里项目基本搭建完成了
2. 引入所需要的UI
- element-ui 引入
// 使用命令安装 element-ui
yarn add element-ui -S
// 安装完成后在main.js 中引入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI, {zIndex: 3000 });
复制代码
这边我就不把所有的ui 引入方式 一一例举了,这边推荐常用的ui有:element-ui、iview、ant 我认为基本符合需求的ui。
3. electron-vue 结构通信处理
打开src/main 目录 我们会看到index.js 和 index.js 两个文件, 这边为了方便开发,这边对index.js进行了一些处理我这边给于分出了三个文件,分别是:
- ipcMain.js
import {ipcMain} from 'electron'
// 与主进程进行通信
const handleShowVersion = (win)=>{
ipcMain.on('show-version',(event,data)=>{
// event.sender.send 为发送实时消息
win.send('show-message',data)
// 这里发信息给vue页面事件(是为了触发更新所预留的一个通信机制)
})
}
export const onLoadIpc = (win)=>{
handleShowVersion(win);
}
复制代码
- 在App.vue 中创建接收事件做一些逻辑上的处理
created() {
// 接收主进程发来的消息
this.$electron.ipcRenderer.on('show-message',(event,message) =>{
console.log(message)
})
}
复制代码
- 在index.js 中的引用
在下文中所有的mainWindow 是创建项目,所自定义的窗口变量
// 引入通信文件
import {onLoadIpc} from './ipcMain'
// 初始化对应的事件方法
app.on('ready', ()=>{
createWindow()
// 初始化所有通信
onLoadIpc(mainWindow)
})
复制代码
4. electron-vue 右下角图标设置
- initTrayIcon.js
import {Menu,Tray} from 'electron'
//创建桌面角标
export const initTrayIcon=(win,app)=> {
const tray = new Tray('build/icons/icon.ico');
const trayContextMenu = Menu.buildFromTemplate([
{
label: '显示主窗口',
click: () => {
win.show()
}
}, {
label: '退出当前软件',
click: () => {
app.quit()
}
}
]);
tray.setToolTip('九为-收银台');
// 右下角图标双击
tray.on('double-click', () => {
win.show()
});
// 右下角图标单击
tray.on('click', () => {
win.show()
});
// 右下角图标右击
tray.on('right-click', () => {
tray.popUpContextMenu(trayContextMenu);
});
}
复制代码
- 在index.js 中的引用
// 引入通信文件
import {initTrayIcon} from './initTrayIcon'
// 初始化对应的事件方法
app.on('ready', ()=>{
createWindow()
// 初始化所有通信
onLoadIpc(mainWindow)
// 设置右下角图标
initTrayIcon(mainWindow,app)
})
复制代码
5. electron-vue 快捷键的设置
- setGolbalShortcut.js
import {globalShortcut} from "electron"
export const handleSetShortcut = (win) =>{
globalShortcut.register('F1+1',()=>{
win.send('show-message','F1+1')
})
}
export const handleUnloadShortcut = () =>{
globalShortcut.unregisterAll()
}
复制代码
- 在index.js 中的引用
// 引入通信文件
import {handleSetShortcut,handleUnloadShortcut} from './setGlobalShortcut'
// 初始化对应的事件方法
app.on('ready', ()=>{
createWindow()
// 初始化所有通信
onLoadIpc(mainWindow)
// 设置右下角图标
initTrayIcon(mainWindow,app)
// 设置全局快捷键
handleSetShortcut(mainWindow)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
// 卸载全局快捷键
handleUnloadShortcut()
}
})
// 关闭当前软件执行
app.on('will-quit', ()=>{
// 卸载全局快捷键
handleUnloadShortcut()
})
复制代码
6. electron-vue 热更新
这里申明一下:更新文件是我从网上找来的,这里我只是做一下 搬运工
import { app, dialog} from 'electron'
// 基础变量定义
const request = require('request')
const { Notification } = require('electron')
const path = require('path');
const fs = require('fs');
const baseUrl = path.join(path.dirname(app.getPath('exe')) ,'./resources');
const packageLocation = `${baseUrl}/app/package.json`;
const fileUrl = "http://www.tt.com/win32/";//这里需要修改为自己的资源外网
var AdmZip = require('adm-zip');
// 进度条
const progress = require('progress-stream');
const url = `${fileUrl}app.zip?v=${new Date().getTime()}`;
// description
export async function updateVersion(event) {
const localpackage = await getLocalPackage(packageLocation);
update(localpackage)
}
async function getLocalPackage(loc) {
return new Promise(async (resolve,reject)=>{
let existed = await isFileExisted(loc)
let con = ''
if (existed){
con = fs.readFileSync(loc,'utf-8')
resolve(con)
}else{
reject("err");
}
})
}
function isFileExisted(loc){
return new Promise( (resolve, reject) => {
fs.access(loc, (err) => {
if (err) {
reject(false);
} else {
resolve(true);
}
})
})
}
function update(localpackage) {
return new Promise((resolve, reject) => {
request(
{
url: `${fileUrl}package.json?v=${new Date().getTime()}`,//请求package.json,与本地对比版本号
},
(error, res, body) => {
console.log(body)
try {
if (error || res.statusCode !== 200) {
throw '更新版本号失败,请联系管理员';
}
const json = JSON.parse(body);
const { version, description } = json;
const localVersion = localpackage.version // 当前版本
console.log('版本号不一致')
if (version != localVersion) {
// mainWindow.webContents.send('updating', '更新中') //主线程给渲染线程
// 提示是否更新
showUpdate(description)
} else {
}
} catch (err) {
reject(err);
}
})
})
}
/**
* download
*/
function downLoad() {
return new Promise((resolve, reject) => {
percentPost(url, 'www.tt.com','/win32/app.zip');
})
}
function showUpdate(desc) {
dialog.showMessageBox({
type:'info',
title:'新版本提示',
message:desc,
buttons:['现在更新','暂不更新'],
cancelId: 1
},function(index){
if(index==0){
console.log('update')
const notification = {
title: '更新提醒:',
body: '正在静默更新,你可以继续你的操作!'
// silent:true
}
new Notification(notification).show()
downLoad().then(() => {
updateNow();
})
}else if(index==1){
console.log('wait')
}
})
}
function updateNow(){
dialog.showMessageBox({
type:'info',
title:'更新完成提示',
message:"更新完成,是否重启",
buttons:['马上体验新版本','稍后体验'],
cancelId: 1
},function(index){
if(index==0){
app.relaunch(); // 重启
app.quit();
}else if(index==1){
console.log('')
}
})
}
function percentPost(url,host,path) {
var req = http.request(
{
host,
path,
method: "HEAD",
},
(res)=> {
//显示进度条
if (res.statusCode == 200) {
res.setEncoding(null);
var str = progress({
length: res.headers["content-length"],
time: 5 /* ms */,
});
str.on("progress", function (progress) {
var percentage = Math.round(progress.percentage).toFixed();
if(percentage<100){
//通知渲染线程同步
// global.eventValue.returnValue = percentage
// 通知渲染线程异步
global.percentage = percentage
global.eventValue.reply('show-percent', percentage) // ELECTRON VERSION>5.0.13
// global.eventValue.sender.send('show-percent',percentage)
}
});
// request.get(url).pipe(str).pipe(fs.createWriteStream(`./di.zip`));
let reader = request.get(url).pipe(str).pipe(fs.createWriteStream(`${baseUrl}/di.zip`));
reader.on('close', () => {
console.log('开始解压')
const unzip = new AdmZip(`${baseUrl}/di.zip`); //下载压缩更新包
unzip.extractAllTo(`${baseUrl}`, /*overwrite*/true); //解压替换本地文件
console.log('覆盖成功');
resolve()
});
} else {
console.log('err')
}
}
);
req.on("error", (e) => {
console.log('err')
});
req.end();
}
复制代码
这里热更新文件对应的git的文件
话不多说 到此结束
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END