快速开发一个客户端软件?
最近发现顺手的工具可以极大的提高工作的效率,海量的密钥信息,网站信息,存储在chrome的标签中还是不方便。所以我就去找免费开源的工具,发现要么功能很复杂,要么好看的要收费。所以我选择自己写一个简单好看又好用的数据管理工具。
注意:开发过程中建议科学上网,因为一些依赖国内网络状况会导致依赖下载很慢而编译失败。
Hello World
学习任何语言的时候,我都习惯先写一个Hello World。
保证自己电脑上有node.js,我这台电脑上没有装过nodejs,直接去官网下载了一个最新版本的。
打开idea创建一个空的项目 在根目录打开终端
#安装 electron
npm install electron -g
#初始化项目
npm init -y
项目结构
新建index.js
const electron = require('electron');
const {
app, // 控制应用生命周期的模块
BrowserWindow, // 创建原生浏览器窗口的模块
} = electron;
// 保持一个对于 window 对象的全局引用,如果不这样做,
// 当 JavaScript 对象被垃圾回收, window 会被自动地关闭
let mainWindow;
function createWindow() {
// 创建浏览器窗口。
mainWindow = new BrowserWindow({width: 800, height: 600});
// 加载应用的 index.html。
// 这里使用的是 file 协议,加载当前目录下的 index.html 文件。
// 也可以使用 http 协议,如 mainWindow.loadURL('http://nodejh.com')。
mainWindow.loadURL(`file://${__dirname}/index.html`);
// 启用开发工具。
mainWindow.webContents.openDevTools();
// 当 window 被关闭,这个事件会被触发。
mainWindow.on('closed', () => {
// 取消引用 window 对象,如果你的应用支持多窗口的话,
// 通常会把多个 window 对象存放在一个数组里面,
// 与此同时,你应该删除相应的元素。
mainWindow = null;
});
}
// Electron 会在初始化后并准备
// 创建浏览器窗口时,调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', createWindow);
// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
// 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
// 否则绝大部分应用及其菜单栏会保持激活。
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// 在 macOS 上,当点击 dock 图标并且该应用没有打开的窗口时,
// 绝大部分应用会重新创建一个窗口。
if (mainWindow === null) {
createWindow();
}
});
新建index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js and Electron
</body>
</html>
Run起来
#启动程序
electron .
最简单的electron项目就跑了起来~
什么是electron?
如果你去搜索这个问题,大多数浏览器会告诉你 Electron 是一个跨平台的、基于 Web 前端技术的桌面 GUI 应用程序开发框架。重点是基于Web前端技术,有过客户端开发经验的同学本能都会觉得写客户端软件应该需要C/C++/C# 之类的语言来开发。但是 Electron 把Web端技术带到了客户端!而且上手容易,开发成本低,因为它使用的是nodejs语言!
快速开发
对于非专门研究技术的选手(我)使用脚手架开发效率是最高的。我对比几款脚手架之后选择了 electron-vue ,因为我写过一段时间的vue,所以上手应该更快点。
初始化项目
打开你的终端,安装vue-cli之后初始化一个项目结构。
在第六步的时候建议全部安装
# 安装 vue-cli 和 脚手架样板代码
npm install -g vue-cli
vue init simulatedgreg/electron-vue exhale
# 安装依赖并运行你的程序
cd exhale
yarn # 或者 npm install
yarn run dev # 或者 npm run dev
初始化完成我们就可以使用Idea打开这个项目,安装依赖、跑起来。
自定义配置
不难发现,electron默认界面还是挺丑的,所以我们先对一些配置进行自定义化
无边框
首先我们要把默认的边框去掉。找到src/main/index.js文件
设置frame属性为false
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
height: 600,
width: 800,
useContentSize: true,
frame:false,
})
窗口设置无边框之后,默认界面是无法拖拽的。我们可以通过CSS属性来控制拖拽范围
应用程序需要在 CSS 中指定 -webkit-app-region: drag 来告诉 Electron 哪些区域是可拖拽的
在可拖拽区域内部使用 -webkit-app-region: no-drag 则可以将其中部分区域排除
我们在App.vue页面的#app div加上可以拖拽的属性。这样我们的无边框应用就设置好了。
最小化、最大化、关闭
无边框把原生的最小化、最大化、关闭按钮也去掉了。
所以我们要自己实现这些功能。
在这里我选择熟悉的Element-ui组件库来画几个图标
#安装element-ui
npm i element-ui -S
在src\renderer\main.js导入ElementUI
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
简单的在App.vue页面右上角画了三个图标
然后在App.vue页面,引入ipcRenderer,来实现了三个按钮的点击事件,
这里的ipcRenderer把它想成一个通信兵,你让它发送的命令,它都会发送到主进程(真正操作软件的地方)里边。
<script>
let ipcRenderer = require('electron').ipcRenderer;
export default {
name: 'exhale',
methods:{
minus:function (){
console.info("最小化")
//发送最小化命令
ipcRenderer.send('window-min');
},
plus:function (){
console.info("最大化")
//发送最大化命令
ipcRenderer.send('window-max');
},
close:function (){
console.info("关闭")
//发送关闭命令
ipcRenderer.send('window-close');
}
}
}
</script>
回到主进程文件src/main/index.js中
在头部引入ipcMain组件
然后监听我们在渲染进程中发送的三个事件,
实现对应的方法
import { ipcMain,app, BrowserWindow } from 'electron'
...
...
//接收最小化命令
ipcMain.on('window-min', function() {
mainWindow.minimize();
})
//接收最大化命令
ipcMain.on('window-max', function() {
if (mainWindow.isMaximized()) {
mainWindow.restore();
} else {
mainWindow.maximize();
}
})
//接收关闭命令
ipcMain.on('window-close', function() {
mainWindow.close();
})
ok,这样我们就实现了自定义最小化、最大化、关闭三个按钮。
托盘Logo
一般客户端软件都是会在后台运行,也就是右下角会有一个托盘图标来显示当前应用在后台运行中
而且这个托盘图标还支持很多功能等等,我们来实现它。
在主进程文件src/main/index.js中
头部文件中引入 Menu, Tray 组件
然后在 createWindow 初始化方法中设置图标的相关属性
import { ipcMain,app, Menu, Tray,BrowserWindow } from 'electron'
//...
//...
//...
function createWindow () {
//...
//...
//...
//设置icon的位置
tray = new Tray("static/logo.png")
const contextMenu = Menu.buildFromTemplate([
{
label: '退出', click: () => {
app.quit();
}
},
])
//双击托盘图标显示主页面
tray.on('double-click',()=>{
mainWindow.show()
})
//设置托盘图标提示文本信息
tray.setToolTip('app')
tray.setContextMenu(contextMenu)
}
现在这个时候,我们发现,我们的关闭按钮写错了,其实是隐藏主进程到后台,让托盘提供关闭功能
我们把close命令改成hide命令
//接收关闭命令
ipcMain.on('window-close', function() {
mainWindow.hide();
})
按照上边设置好之后。
托盘
提示
退出
打包
看起来我们的app只剩下把页面写好就行了,这个步骤就需要细心的开发了。
我们开发完之后,如何打包出来一个安装程序供别人使用呢?
打包的话,我们得需要一个logo,
打开package.json文件修改我们的icon位置
"mac": {
"icon": "static/logo.png"
},
"win": {
"icon": "static/logo.png"
},
"linux": {
"icon": "static/logo.png"
}
其实我们打开package.json文件时可以发现,脚手架已经帮我们做好了。
"scripts": {
"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 run build 命令就行了
可是,我运行之后是报错了。
E:\WebStorm\exhale\.electron-vue\build.js:45
const tasks = new Listr(
^
SyntaxError: Identifier 'tasks' has already been declared
搜索一番后,找到.electron-vue\build.js文件,确实是重名了,我们修改一下名字
重新打包仍然报错
E:\WebStorm\exhale\.electron-vue\build.js:38
const m = new Multispinner(taskss, {
^
ReferenceError: Multispinner is not defined
编译过程中没有地方用到这段逻辑,果断注释掉。已经向官方提了BUG
再次打包
可以看到 build/win-unpacked 目录下会打出来一个 exhale Setup 1.0.0.exe的安装包
运行就可以安装了。
下载使用
上边就是开发一个客户端所需要的基础知识,如果有兴趣可以学习electron官方文档。
我按照自己的需求开发了一款工具,有兴趣的话可以下载使用~
https://github.com/FangPengbo/exhale