【From】 http://www.myk3.com/arc-8856.html
很久没有更新博客,人越来越懒了,唉 说好做的electron教程距离上次玩electron已经过去了好几个月了。。
这次对electron做一个实战流程的介绍,关于electron的介绍,可以看这里 http://www.myk3.com/arc-4486.html
关于electron的demo安装,请看 http://www.myk3.com/arc-4483.html
使用 electron 您需要有一定的nodejs使用基础,能熟练使用js语言。那么,以这篇文档http://www.myk3.com/arc-4486.html 的项目为例,来介绍其中用到的技巧和流程。
思想:项目的界面采用html+css+js完成,关于顶部的标题栏和最大化最小化 关闭按钮也是用html完成。后面说他们与electron 的交互。而electron 提供包含在线网页的容器框架,一个electron窗口包含一个在线网页。
假如我们写好了登录页面,这里面有如下的地方需要雨electron 交互 甚至与node模块交互。分别是 点击页面中的新窗口打开的连接,会弹出新的无标题栏窗口,我们拦截点击事件,让其用默认浏览器打开。然后是自己写的标题栏的拖动,最大化,最小化,关闭按钮的响应。点击登录打开新窗口的响应。以及穿够页面加载完毕才显示。 如果你的网页载入很慢,建议html本地化,我这里的服务器性能不错,所以直接在线加载,速度也不错。
那么对上面页面中需要与electron 响应的功能,下面一一说明。
先创建一个登录窗口,并加载登录页面作为gui驱动。在main.js中写。修改你安装的demo中的createWindow方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function
createWindow () {
mainWindow =
new
BrowserWindow({
width: 500,
//窗口宽度
height: 600,
//窗口高度
resizable:
false
,
//能否改变窗体大小
'accept-first-mouse'
:
true
,
title:
'佳乐社区'
,
frame:
false
,
show:
false
,
//是否显示界面 先设置否
//icon:'3.ico',
hasShadow :
true
})
mainWindow.loadURL(baseUrl+
'user.php?a=basic&f=login&app=1'
)
}
|
我们让其加载完毕显示,加上在载入完毕显示的代码
1
2
3
|
mainWindow.webContents.on(
'did-finish-load'
,
function
() {
mainWindow.show();
});
|
这样登录窗口就显示了。接下来标题栏的拖动。很简单在标题栏的html元素上加上 css
1
|
-webkit-app-region: drag;
|
对于加上-webkit-app-region: drag;的元素,只能拖动,而我们的最大化最小化,关闭都包含在其中,我们让他们可以点击,单独设置这几个按钮加上css
1
|
-webkit-app-region: no-drag;
|
如图:
当然,你也可以保留window的标题栏,这样就不用自己写事件处理了,不过,小安觉得自带的太丑了,所以重写。
接下来对于页面中target="blank"a连接弹出的新窗口做拦截,让其用自带的浏览器打开,如果用无标题栏的electron打开,很丑,具体思想,调用node的exec函数执行cmd,不过需要先拦截,具体代码:
1
2
3
4
5
6
|
mainWindow.webContents.on(
'new-window'
,
function
(event,url,fname,disposition,options) {
var
exec = require(
'child_process'
).exec;
//加载node模块 url是将要跳转的地址
//拦截url调用外部浏览器打开
exec(
'start '
+url,
function
(err,stdout,stderr){});
event.preventDefault();
});
|
然后我们来看 最大化,最小化,关闭的处理
这里要介绍下electron的ipc通信,具体的专业术语不知道,反正就是让main.js和各个electron窗口之间能通信,互相控制,官方有个规则,一切的electron窗口原生操作都尽量在main.js中处理,这是安全的,虽然在各个electron窗口的html页面也可以写窗口的相关操作代码。
用实例来演示ipc的用法。main.js中创建了登录的electron窗口,在点击窗口中html写的最小化按钮时,触发页面js,我用jquery来绑定点击事件
1
2
3
4
5
|
var
ipc = require(
'electron'
).ipcRenderer;
//绑定最小化
f.$doc.delegate(
'.window_min'
,
'click'
,
function
(e){
ipc.send(
'login-window-min'
);
//发送了一个login-window-min的消息,这个消息将在 main.js中接受,名称可以自定义。
})
|
记得在html页面中使用ipc一定要先引用
1
|
require(
'electron'
).ipcRenderer;
|
而在main.js中不一样,用这句 这里语法是es6,新一代的js语法,童鞋们可以学习下
1
|
const ipc = electron.ipcMain
|
在main.js中处理接受到消息login-window-min 代码如下:
1
2
3
4
|
//登录窗口最小化
ipc.on(
'login-window-min'
,
function
(){
mainWindow.minimize();
})
|
mainWindow是我们的登录窗口创建后返回的句柄,它是全局的,所以在main.js的任何地方都可以用,它的定义是全局的
1
|
let mainWindow
|
而最大化和关闭都差不多。
完整代码登录的html中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
f.$doc.delegate(
'.window_close'
,
'click'
,
function
(e){
ipc.send(
'login-window-close'
);
})
f.$doc.delegate(
'.window_min'
,
'click'
,
function
(e){
ipc.send(
'login-window-min'
);
})
var
is_window_max =
false
;
f.$doc.delegate(
'.window_max'
,
'click'
,
function
(e){
ipc.send(
'login-window-max'
);
if
(is_window_max){
is_window_max =
false
;
$(
this
).find(
'div'
).css(
'fontSize'
,
'24px'
);
}
else
{
$(
this
).find(
'div'
).css(
'fontSize'
,
'20px'
);
is_window_max =
true
;
}
})
|
main.js中的处理过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//关闭所有窗口 调用ipc模块 主进程
ipc.on(
'login-window-close'
,
function
(){
app.quit();
})
//登录窗口最小化
ipc.on(
'login-window-min'
,
function
(){
mainWindow.minimize();
})
//登录窗口最大化
ipc.on(
'login-window-max'
,
function
(){
if
(mainWindow.isMaximized()){
mainWindow.restore();
}
else
{
mainWindow.maximize();
}
})
|
应为登录窗口是主窗体,所以当登录窗体关闭,应用结束,用 app.quit();
接下来介绍登录按钮点击后创建新electron窗口,在登录html页面中写绑定,在ajax登录验证成功的回调中打开新窗体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
success:
function
(r){
$(
'#login-error'
).hide();
$(
'#login-error'
).fadeIn(500);
$(
'.notice-descript'
).text(r.msg);
if
(r.status){
//检查是否记住密码
lo.remember_pwd();
//如果是软件登录则打开内容窗口
if
(f.app){
ipc.send(
'content-window-show'
,r.data);
setTimeout(
function
(){
$(
'#fm-login-submit'
).attr(
'disabled'
,
false
);
},4000);
return
false
;
}
$(
'.icon-notice'
).removeClass(
'icon-error'
).addClass(
'icon-success'
);
$(
'.loading-mask'
).show();
if
(f.backurl){
//如果是其他地方跳转过来的登录
location.href =
'http://'
+f.backurl;
}
else
{
location.href =
'user.php?a=index&f=home&app='
+f.app;
}
}
else
{
$(
'#fm-login-submit'
).attr(
'disabled'
,
false
);
}
}
|
主要是这一句
1
|
ipc.send(
'content-window-show'
,r.data);
|
发送打开新窗体的命令,带了参数r.data.
在main.js中我们来写监听并响应,其实和socket.io的编写方式差不多。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
//内容窗口显示 一般登录成功才行
var
contentWindow =
null
;
var
remindWindow =
null
;
ipc.on(
'content-window-show'
,
function
(event,u){
UserInfo = u;
console.log(u);
//先隐藏登录窗口
setTimeout(
function
(){
mainWindow.hide();
},1800);
//创建提醒窗口
creatRemindWindow();
//创建内容窗口
if
(contentWindow){
contentWindow.focus();
return
;
}
contentWindow =
new
BrowserWindow({
frame:
false
,
height: 700,
resizable:
false
,
width: 1240,
//icon:'3.ico',
frame:
false
,
show:
false
,
});
contentWindow.loadURL(baseUrl+
'user.php?a=index&f=home&app=1'
);
contentWindow.webContents.on(
'did-finish-load'
,
function
() {
contentWindow.show();
});
contentWindow.setSkipTaskbar(
true
);
//contentWindow.webContents.openDevTools()
contentWindow.on(
'closed'
,
function
() {
contentWindow =
null
;
});
contentWindow.webContents.on(
'new-window'
,
function
(event,url,fname,disposition,options) {
var
exec = require(
'child_process'
).exec;
//拦截url调用外部浏览器打开
exec(
'start '
+url,
function
(err,stdout,stderr){});
event.preventDefault();
});
ipc.on(
'content-window-min'
,
function
(){
contentWindow.minimize();
})
})
|
我们看见了其实创建过程和创建登录窗口差不多,通过加载不同的
1
|
loadURL(baseUrl+
'user.php?a=index&f=home&app=1'
|
url来显示不同的页面作为GUI。
到这里,如果你能看明白,那么已经可以用electron做项目开发了,毕竟,核心的东西就这些,其他是一些小技巧,比如右下角图标和右键菜单的使用,代码如下:
载入模块
1
|
const {Menu,Tray, MenuItem} = electron;
|
实现代码
1
2
3
4
5
6
7
8
|
//显示右下角图标
tray =
new
Tray(path.join(__dirname,
'3.ico'
))
//右下角的图标
const contextMenu = Menu.buildFromTemplate([
//右键菜单项 可以是多个 这里只有关闭一个项
{label:
'关闭'
, click:
function
(){
app.quit();
}},
//{label: 'Item2', type: 'radio'},
]);
|
给右下角图标绑定右键菜单
1
|
tray.setContextMenu(contextMenu);
|
绑定双击事件,让其窗口显示
1
2
3
4
5
6
7
|
tray.on(
'double-click'
,
function
(){
if
(contentWindow){
contentWindow.show();
}
else
{
mainWindow.show();
}
})
|
上面这些代码需要写在createWindow 创建登录窗口的函数体中。
如图:
如果使用右下角图标,那么下方的任务栏不应该在显示程序信息,隐藏方法为
1
2
|
//隐藏任务栏
mainWindow.setSkipTaskbar(
true
);
|
右键菜单不仅可以绑定给右下角图标,也可以是html元素的任何位置,具体的代码我看看 比如绑定到h1标签上,在html中写js代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//右键菜单
const {remote} = require(
'electron'
);
const {Menu,Tray, MenuItem} = remote;
const menu =
new
Menu();
menu.append(
new
MenuItem({label:
'查看'
, click() { console.log(
'item 1 clicked'
); }}));
//menu.append(new MenuItem({type: 'separator'}));
menu.append(
new
MenuItem({label:
'编辑'
, type:
'checkbox'
, checked:
true
}));
var
h1 = document.getElementById(
'rightButton'
);
h1.addEventListener(
'contextmenu'
, (e) => {
e.preventDefault();
menu.popup(remote.getCurrentWindow());
},
false
);
|
当然也可以在html中(非main.js)写关闭等操作,虽然是不安全的,不推荐
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
const BrowserWindow = require(
'electron'
).remote.BrowserWindow
const path = require(
'path'
)
const newWindowBtn = document.getElementById(
'openNewWindwo'
)
const clo = document.getElementById(
'close'
)
newWindowBtn.addEventListener(
'click'
,
function
(event) {
const modalPath = path.join(
'file://'
, __dirname,
'modal.html'
)
let win =
new
BrowserWindow({id:2, width: 400, height: 320,title:
'test'
})
win.loadURL(`file:
//${__dirname}/model.html`)//指定渲染的页面
//win.show()//打开一个窗口
//win.webContents.openDevTools()
win.webContents.on(
'did-finish-load'
,
function
() {
win.show();
});
win.on(
'move'
, updateReply)
win.on(
'resize'
, updateReply)
win.on(
'closed'
,
function
() { win =
null
})
function
updateReply () {
const mangageWindowReply = document.getElementById(
'manage-window-reply'
)
const message = `Size: ${win.getSize()} Position: ${win.getPosition()}`
mangageWindowReply.innerText = message
}
})
|
在html页面中(非main.js)枚举所有窗体
1
2
3
|
const {dialog} = require(
'electron'
).remote;
win = BrowserWindow.getAllWindows();
win[0]就是第一个创建的窗口
|
最后介绍下文件对话框的使用 在html中写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//打开文件框 方便读写文件操作
$(
'#dialog'
).on(
'click'
,
function
(e){
const {dialog} = require(
'electron'
).remote;
win = BrowserWindow.getAllWindows();
dialog.showOpenDialog(win[0],{properties: [
'openFile'
,
'multiSelections'
],filters: [
//{name: 'Images', extensions: ['jpg', 'png', 'gif']},
//{name: 'Movies', extensions: ['mkv', 'avi', 'mp4']},
//{name: 'Custom File Type', extensions: ['as']},
{name:
'All Files'
, extensions: [
'*'
]}
]},
function
(r){
console.log(r);
})
})
|
好了,使用上大概我也就会这些,更多的操作可以去看官方英文文档,比较详细,希望能让你更快的学会electron,下一篇文档小安会抽时间做electron的打包教程,以及跨平台,其实只要打包后,下载对应的版本,跨平台修改的代码很少,至少对我我的这个项目而言,搬运到mac系统上只删除了几行代码就能运行了,祝你好运。感谢阅读
本文来自:绵阳史安平个人博客.励志于每一位朋友
欢迎转载,转载请注明本文链接: electron实战开发详细流程
http://www.myk3.com/arc-8856.html