【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
