小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

用Electron開發(fā)桌面應用 | @Get社區(qū)

 念念爸 2017-05-03

本文主要介紹了如何用Electron配合JavaScript等web技術創(chuàng)建桌面應用。

Bazzzinga威 同學翻譯自 Medium。https:///developers-writing/building-a-desktop-application-with-electron-204203eeb658

什么是JavaScript桌面應用

在我心中,桌面應用一直占據著一個特殊的地位。隨著瀏覽器,移動設備變得越來越強大,被移動和web應用取代的桌面應用呈穩(wěn)定下滑趨勢。但編寫桌面應用還是有很多優(yōu)勢的--它們會一直存在于你的開始目錄或者Dock欄中,可以被alt(cmd)+tab來回切換,并且大部分比web應用與底層系統(tǒng)聯(lián)系的更緊密(快捷鍵,通知推送等)。

本文中,我會引導你用JavaScript創(chuàng)建一個簡單桌面應用,接觸相關的概念。

用JavaScript編寫桌面應用的核心思想是編寫一套資料庫,把它分別打包來兼容各個操作系統(tǒng)。不需要創(chuàng)建原生桌面應用的知識,維護起來更簡單。現在,用JavaScript開發(fā)桌面應用主要是使用Electron或者NW.js。盡管兩種工具提供的功能相似,我更喜歡Electron,因為它有一些我認為很重要的優(yōu)勢。到頭來,你用哪一個都沒有問題。

基本假定

我假定你已經有了文本編輯器(或者IDE),并且安裝了Node.js和npm。同樣假定你已經掌握HTML/CSS/JavaScript的知識(如果會Node.js和CommonJS模塊更好,不過并不是必需的),這樣可以將重點放在學習Electron,而不需要擔心創(chuàng)建用戶界面(其實就是普通的web頁面)。如果你不符合前面幾點,你也許會感到有些迷惑,我推薦你看下我的前一篇文章來學習基礎。

Electron 概述

簡單來說,Electron為用純JavaScript創(chuàng)建桌面應用提供了運行時。原理是,Electron調用你在package.json中定義的main文件并執(zhí)行它。main文件(通常被命名為main.js)會創(chuàng)建一個內含渲染完的web頁面的應用窗口,并添加與你操作系統(tǒng)的原生GUI(圖形界面)交互的功能。

詳細地說,當用Electron啟動一個應用,會創(chuàng)建一個主進程。這個主進程負責與你系統(tǒng)原生的GUI進行交互并為你的應用創(chuàng)建GUI(在你的應用窗口)。

僅啟動主進程并不能給你的應用用戶創(chuàng)建應用窗口。窗口是通過main文件里的主進程調用叫BrowserWindow的模塊創(chuàng)建的。每個瀏覽器窗口會運行自己的渲染進程。渲染進程會在窗口中渲染出web頁面(引用了CSS,JavaScript,圖片等的HTML文件)。web頁面是Chromium渲染的,因為各系統(tǒng)下標準是統(tǒng)一的的,所以兼容性很好。

舉例來說,如果你有一個計算器應用,主進程會初始化一個窗口來呈現實際的web頁面(計算器)。

雖說只有主進程才和系統(tǒng)原生GUI交互,還是有技術可以把部分任務轉到渲染進程中運行。

主進程通過一套可直接調用的Electron模塊與原生GUI交互,桌面應用可以使用所有的Node模塊,如用node-notifier模塊來推送系統(tǒng)通知,request模塊來發(fā)起HTTP請求等。


Hello, world!

練習用資料庫

現在,讓我們做好準備,用傳統(tǒng)的「Hello,World」來開始。

本指南的同步練習資料庫是sound-machine-tutorial。首先把資料庫clone下來:

git clone https://github.com/bojzi/sound-machine-electron-guide.git

進入sound-machine-tutorial文件夾,用下面的代碼在git的tag之間切換:

git checkout <tag-name>

我會提示你該用哪個tag:

請切換至:
git checkout 00-blank-repository

當你clone完代碼,切換到你想要的tag,運行:

npm install

這樣你安裝好全部Node模塊了。

如果你不能轉換到另一個tag,最簡單的辦法是重置你的資料庫狀態(tài)再切換:

git add -A
git reset --hard

開始

請切換到00-blank-repository這個tag:
git checkout 00-blank-repository

在項目文件夾中新建package.json文件,寫入下面的內容:

這個簡單的package.json文件:

  • 設置應用的名字和版本號,
  • 設置Electron主進程運行的腳本(main.js),
  • 設置一個很實用的快捷鍵--在你的CLI(命令行)中可以用「npm start」方便地啟動應用。

現在該安裝Electron了,最簡單的方式是用npm為你的操作系統(tǒng)安裝預構建的二進制文件。并在package.json文件中將它設置為開發(fā)依賴(用--save-dev命令后綴自動設置)。在CLI中運行命令:

npm install --save-dev electron-prebuilt

預構建的二進制文件是為所在的操作系統(tǒng)量身訂造的,可以運行「npm start」。我們將它作為開發(fā)依賴安裝是因為只在開發(fā)過程中用到它。

就這樣,Electron開發(fā)所需的一切都準備好了。

跟世界打個招呼

新建app文件夾,在其中新建有下面代碼的index.html文件:

Hello, world!

在項目的根目錄下新建一個main.js文件。Electron的主進程將用它來啟動并創(chuàng)建「Hello, world」桌面應用。main.js中的代碼:

'use strict';


var app = require('app');
var BrowserWindow = require('browser-window');


var mainWindow = null;


app.on('ready', function() {
    mainWindow = new BrowserWindow({
        height: 600,
        width: 800
    });


    mainWindow.loadUrl('file://' + __dirname + '/app/index.html');
});

沒什么嚇人的,不是嗎?

「app」模塊會控制應用的生命周期(例如, 對應用的ready狀態(tài)做出反應)。

「BrowserWindow」模塊為你創(chuàng)建窗口。

「mainWindow」對象是你應用的主窗口,被聲明成null,否則當JavaScript垃圾回收掉這個對象時,窗口會被關閉。

當「app」捕獲ready事件,「BrowserWindow」創(chuàng)建一個800*600大小的窗口。

瀏覽器窗口的渲染進程會渲染index.html文件。

在CLI中鍵入下面命令啟動「Hello, World!」:

npm start

現在為你的第一個Electron程序歡呼吧。



開發(fā)真正的應用

超棒的發(fā)聲器

首先,什么是發(fā)聲器?

發(fā)聲器當你點擊不同按鈕時會播放不同聲音的小設備,大部分是卡通或特效聲。是在辦公室用來放松心情的,很有趣的工具,隨著開發(fā)的進行,會碰到的很多新的概念,所以這也是一個很好的開發(fā)桌面應用的實例(也是一個非常棒的發(fā)聲器)。

我們將完成的功能和探索的概念包括:

  • 基礎發(fā)聲器(基本的瀏覽器窗口初始化),
  • 關閉發(fā)聲器(在主進程和渲染進程之間遠程通信),
  • 不需要把焦點切到應用就可以播放聲音(全局快捷鍵),
  • 創(chuàng)建快捷鍵的設定界面,來變更鍵位(Shift,Ctrl和Alt)(保存在用戶的個人文件夾設置中),
  • 加一個托盤圖標(遠程創(chuàng)建原生GUI元素,了解菜單和托盤圖標),
  • 打包你的應用(把你的應用打包成 Mac,Windows,Linux下可用的版本)。

實現發(fā)聲器的基礎功能

應用的結構

你已經實現了一個運行正常的「Hello World!」應用,現在是時候實現一個發(fā)聲器應用了。

典型的發(fā)聲器功能包括幾排按鈕,點擊播放聲音,這些聲音大部分是卡通式的或者特效式的(如大笑,鼓掌,玻璃碎裂聲等)。

那就是我們要完成的第一個功能--能對點擊能做出響應的發(fā)聲器。

應用結構是比較簡單的。

在應用的根目錄,保存著package.json文件,main.js文件和其他文件。

app文件夾保存HTML文件,其中在css,js,wav和img文件夾中保存相應類型的文件。

為了簡便,web頁面所需的全部文件都已經保存在資料庫的初始狀態(tài)中?,F在切換到01-start-project這個tag。如果你之前跟著指南操做,創(chuàng)建了「Hello World!」應用,你需要先重置資料庫再切換:

If you followed along with the "Hello, world!" example:
git add -A
git reset --hard
切換到01-start-project這個tag:
git checkout 01-start-project

為了簡便,發(fā)聲器將只有兩種聲音,但擴展到全部16種聲音也非常簡單,只需要其他聲音和圖標文件,修改index.html就可以。

完成主進程

用main.js定義發(fā)聲器的外觀。用下面的代碼代替原內容:

'use strict';

var app = require('app');
var BrowserWindow = require('browser-window');

var mainWindow = null;

app.on('ready', function() {
    mainWindow = new BrowserWindow({
        frame: false,
        height: 700,
        resizable: false,
        width: 368
    });

    mainWindow.loadUrl('file://' + __dirname + '/app/index.html');
});

我們用傳給「app」模塊的尺寸參數,自定義了新建窗口的大小,設定它是固定尺寸并且無邊欄。它會浮在你的桌面上,就像真的發(fā)聲機一樣。

現在的問題是 -- 如何移動一個沒有邊欄的窗口(沒有標題欄),如何關閉它?

我很快就會講解自定義窗口(應用)關閉(并介紹一種主進程和渲染進程通信的方法),但拖動部分很簡單,在index.css(app/css文件夾下)文件中:

html,
body {
    ...
    -webkit-app-region: drag;
    ...
}

-webkit-app-region:drag;使整個html變成一個可拖動的對象?,F在有一個問題,你不能點擊可拖動對象里的按鈕。答案就是-webkit-app-region: no-drag;能定義不可拖動(但是可以點擊)的對象,參考index.css的中的代碼:

.button-sound {
    ...
    -webkit-app-region: no-drag;
}

在窗口中顯示發(fā)聲器

main.js文件現在可以新建一個窗口來顯示發(fā)聲器。如果用npm start啟動應用,你可以看到發(fā)聲器非常逼真。現在點擊沒有反應,這并不奇怪,我們只有一個靜態(tài)的web頁面。

添加下面的代碼到index.js(app/js文件夾)文件中會添加交互效果:

'use strict';

var soundButtons = document.querySelectorAll('.button-sound');

for (var i = 0; i < soundButtons.length; i++) {
    var soundButton = soundButtons[i];
    var soundName = soundButton.attributes['data-sound'].value;

    prepareButton(soundButton, soundName);
}

function prepareButton(buttonEl, soundName) {
    buttonEl.querySelector('span').style.backgroundImage = 'url("img/icons/' + soundName + '.png")';

    var audio = new Audio(__dirname + '/wav/' + soundName + '.wav');
    buttonEl.addEventListener('click', function () {
        audio.currentTime = 0;
        audio.play();
    });
}

代碼很簡單,我們:

  • 查詢所有聲音按鈕,
  • 遍歷所有的按鈕讀取data-sound屬性,
  • 給每個按鈕加背景圖,
  • 給每個按鈕加一個點擊事件來播放音頻(調用HTML AudioElement接口

CLI中輸入下面命令來測試應用:

npm start



用遠程事件從瀏覽器窗口關閉應用

請切換到02-basic-sound-machine這個tag:
git checkout 02-basic-sound-machine

簡要重述--應用窗口(更準確的說是渲染進程)應該不能與GUI(用來關閉窗口)通信的,官方的Electron快速入門指南寫到:

在web頁面,不允許調用原生GUI相關的API,因為在web頁面管理原生GUI資源是很危險的,會很容易泄露資源。如果你想在web頁面施行GUI操作,web頁面的渲染進程必須要與主進程通信,請求主進程來完成這些操作。

Electron提供ipc(進程間通信)模塊來實現這類通信。ipc模塊可實現從通道訂閱消息,發(fā)送消息給通道的訂閱者,通道區(qū)分消息的接收者,用字符來標識(例如,通道1,通道2)。消息也可以包含數據。當接收到消息,訂閱者可以做出反應,甚至回復消息。消息最大的好處就是隔離 -- 主進程不必知道哪個渲染進程發(fā)出消息。

這正是我們在做的 -- 主進程(main.js)訂閱「close-main-window」通道的消息,關閉按鈕被點擊時,渲染進程(index.js)通過通道發(fā)出消息。

在main.js里添加下面的代碼,從通道訂閱消息:

var ipc = require('ipc');

ipc.on('close-main-window', function () {
    app.quit();
});

引入ipc模塊后,通過通道訂閱消息就變得很簡單,on()方法設置訂閱的通道名,定義回調函數。

渲染進程要通過通道發(fā)送消息,將下面代碼加入index.js:

var ipc = require('ipc');

var closeEl = document.querySelector('.close');
closeEl.addEventListener('click', function () {
    ipc.send('close-main-window');
});

同樣,我們引入ipc模塊,給關閉按鈕的元素綁定一個click事件。當點擊關閉按鈕時,通過「close-main-window」通道的send()方法發(fā)送消息。

這里還有個小問題,如果不注意會卡住你,我們已經討論過--可拖動區(qū)域的可點擊性。index.css需要把關閉按鈕定義成不可拖動:

.settings {
    ...
    -webkit-app-region: no-drag;
}

就這樣,現在可以點擊關閉按鈕關閉我們的應用了。因為要監(jiān)聽事件或傳遞參數,通過ipc模塊通信比較復雜。我們后面會看到一個傳遞參數的例子。


用全局快捷鍵播放聲音

請切換到名為03-closable-sound-machine的tag:
git checkout 03-closable-sound-machine

基礎的發(fā)聲器工作順利,但是我們有一個易用性問題--如果發(fā)聲器一定需要切到應用窗口,再點擊才能播放,這個發(fā)聲器有什么用?

這時我們需要的就是全局快捷鍵。Electron提供一個全局快捷鍵模塊,允許你監(jiān)聽自定義的鍵盤組合并做出反應。鍵盤組合也被叫做加速器,是一系列鍵盤點擊組成的字符串(例如 “Ctrl+Shift+1”)。

既然我們想要捕捉一個原生GUI事件(全局快捷鍵),然后在應用窗口做出反應(播放聲音),我們仍用ipc模塊在主進程和渲染進程之間通信。

在深入到代碼層面前,有兩件事要考慮:

  1. 全局快捷鍵應在app的「ready」事件觸發(fā)后被注冊(在ready代碼塊中),
  2. 當通過ipc從主進程發(fā)送消息到渲染進程的時候,你要引用到那個窗口(就像「createWindow.webContent.send('channel')」)

記住這些,現在用下面的代碼來修改我們的main.js文件:

var globalShortcut = require('global-shortcut');

app.on('ready', function() {
    ... // existing code from earlier

    globalShortcut.register('ctrl+shift+1', function () {
            mainWindow.webContents.send('global-shortcut', 0);
    });
    globalShortcut.register('ctrl+shift+2', function () {
        mainWindow.webContents.send('global-shortcut', 1);
    });
});

首先,我們需要引入global-shortcut模塊。然后當我們的程序加載完成,我們注冊兩個快捷鍵--一個響應Ctrl,Shift,1組合鍵,另一個響應Ctrl,Shift,2組合鍵。兩者都會通過「global-shortcut」通道發(fā)送一條帶一個參數的消息。我們用這些參數來播放相應的聲音。在index.js中加入以下代碼:

ipc.on('global-shortcut', function (arg) {
    var event = new MouseEvent('click');
    soundButtons[arg].dispatchEvent(event);
});

為了方便,我們會模擬一次按鈕點擊,用我們創(chuàng)建的soundButton選擇器給按鈕綁定一個播放聲音。當收到帶有參數1的消息,我們在soundButton[1]元素上模擬一次鼠標點擊(在正式環(huán)境的應用,你應該封裝播放聲音的代碼,并執(zhí)行它)。


在新的窗口修改鍵位配置

切換到名為04-global-shortcuts-bound的tag:
git checkout 04-global-shortcuts-bound

系統(tǒng)同時運行很多應用程序,我們預想的快捷鍵可能已經被占用了。這正是我們將要新建一個設置窗口,保存我們想要的鍵位修改的原因。

要實現這個目標,我們需要:

  • 主窗口要有一個設置按鈕,
  • 一個設置窗口(需要相應的HTML,CSS和JavaScript文件),
  • ipc消息用來打開,關閉設置窗口及更新全局快捷鍵,
  • 保存或讀取用戶系統(tǒng)里JSON格式的設置文件。

設置按鈕和設置窗口

類似關閉主窗口,當點擊設置按鈕時我們通過通道從index.js發(fā)送消息。將下面代碼加入index.js:

var settingsEl = document.querySelector('.settings');
settingsEl.addEventListener('click', function () {
    ipc.send('open-settings-window');
});

點擊設置按鈕后,通道「open-settings-window」會發(fā)送一條消息到主進程。main.js現在需要做出響應,新建一個窗口,將下面代碼插入main.js:

var settingsWindow = null;

ipc.on('open-settings-window', function () {
    if (settingsWindow) {
        return;
    }

    settingsWindow = new BrowserWindow({
        frame: false,
        height: 200,
        resizable: false,
        width: 200
    });

    settingsWindow.loadUrl('file://' + __dirname + '/app/settings.html');

    settingsWindow.on('closed', function () {
        settingsWindow = null;
    });
});

沒有什么新概念,我們會像打開主窗口一樣打開新的設置窗口。不同之處是要先檢查設置窗口是不是已經被打開,以防重復打開。

打開后,需要一種方法關閉設置窗口。同樣的,我們會通過通道發(fā)送一條消息,但這次消息是從settings.js發(fā)出,將下面代碼寫入setting.js:

'use strict';

var ipc = require('ipc');

var closeEl = document.querySelector('.close');
closeEl.addEventListener('click', function (e) {
    ipc.send('close-settings-window');
});

在main.js里面監(jiān)聽那個通道,代碼如下:

ipc.on('close-settings-window', function () {
    if (settingsWindow) {
        settingsWindow.close();
    }
});

我們的設置窗口就完成了。

保存和讀取用戶的設置

切換到名為05-settings-window-working的tag:
git checkout 05-settings-window-working

與設置窗口交互,保存設置,再讀取到我們的應用的過程大致是這樣的:

  • 編寫一個可以保存和讀取我們在JSON文件中保存設置信息的辦法,
  • 初始化設置窗口時,顯示這些設置,
  • 通過客戶的交互更新設置,
  • 通知主程序新的設置。

我們可以簡單的保存和讀取main.js中的設置,但模塊把邏輯抽象出來,以便我們可以在不同的地方引用,這看看起來更好。

Working with a JSON configuration

那就是我們新建configuration.js的原因。Node.js用CommonJS模塊規(guī)范,這意味著你只可以暴露你的API,而其他文件或方法會引用API提供的方法。

為了讓保存和讀取更簡便,使用nconf模塊,它已經為我們抽象出讀取和寫入JSON文件的方法,非常符合我們的需求。但首先,我們要在CLI中執(zhí)行下面的命令將它引入項目中:

npm install --save nconf

npm將nconf模塊作為應用的依賴安裝。在我們打包應用給終端用戶時(相對用save-dev參數會只在開發(fā)環(huán)境中引入模塊)將被引入和使用。

configuration.js文件非常的簡單,在項目根目錄下新建configuration.js文件,寫入代碼:

'use strict';

var nconf = require('nconf').file({file: getUserHome() + '/sound-machine-config.json'});

function saveSettings(settingKey, settingValue) {
    nconf.set(settingKey, settingValue);
    nconf.save();
}

function readSettings(settingKey) {
    nconf.load();
    return nconf.get(settingKey);
}

function getUserHome() {
    return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME'];
}

module.exports = {
    saveSettings: saveSettings,
    readSettings: readSettings
};

nconf只需要知道你的設置要保存到哪里,這里我們設置為客戶的主文件夾和一個文件名。獲取用戶的主文件夾非常簡單,只需要區(qū)別不同系統(tǒng)調用Node.js(process.env)(如用getUserHome()方法)。

通過nconf的內建方法來保存或讀取設置(set()方法保存,get()方法讀取,用save()和load()方法進行文件操作),用符合CommonJS規(guī)范的module.exports語法來導出API。

初始化修改的快捷鍵

在我們進行設置的交互之前,應初始化設置,以防我們先啟動應用丟失設置信息。我們把變更鍵保存在一個數組中,數組以「shortcutKeys」為鍵,在main.js里初始化,我們首先要引用configuration模塊:

'use strict';

var configuration = require('./configuration');

app.on('ready', function () {
    if (!configuration.readSettings('shortcutKeys')) {
        configuration.saveSettings('shortcutKeys', ['ctrl', 'shift']);
    }
    ...
}

嘗試讀取「shortcutKeys」鍵對應的值,如果讀取不到,就設置一個初始值。

現在要重寫main.js中的全局快捷鍵,這個方法可以在后面更新設置的時候直接調用。 去掉原來在main.js中注冊快捷鍵的方法,改成:

app.on('ready', function () {
    ...
    setGlobalShortcuts(); 
}

function setGlobalShortcuts() {
    globalShortcut.unregisterAll();

    var shortcutKeysSetting = configuration.readSettings('shortcutKeys');
    var shortcutPrefix = shortcutKeysSetting.length === 0 ? '' : shortcutKeysSetting.join('+') + '+';

    globalShortcut.register(shortcutPrefix + '1', function () {
        mainWindow.webContents.send('global-shortcut', 0);
    });
    globalShortcut.register(shortcutPrefix + '2', function () {
        mainWindow.webContents.send('global-shortcut', 1);
    });
}

方法會重置全局快捷鍵,現在我們可以設置新的快捷鍵,從設置文件讀取變更鍵數組,轉換類加速器規(guī)則字符串,再注冊全局快捷鍵。

與設置窗口交互

回到settings.js,我們要綁定click事件來修改我們的全局快捷鍵。首先,我們遍歷所有勾選的復選框(從configuration模塊中讀?。?/p>

var configuration = require('../configuration.js');

var modifierCheckboxes = document.querySelectorAll('.global-shortcut');

for (var i = 0; i < modifierCheckboxes.length; i++) {
    var shortcutKeys = configuration.readSettings('shortcutKeys');
    var modifierKey = modifierCheckboxes[i].attributes['data-modifier-key'].value;
    modifierCheckboxes[i].checked = shortcutKeys.indexOf(modifierKey) !== -1;
    
    ... // Binding of clicks comes here
}

現在我們要給復選框綁定行為。記得設置窗口(渲染進程)不能改動GUI綁定。這意味著我們需要從setting.js通過ipc發(fā)送消息(后面會處理消息):

for (var i = 0; i < modifierCheckboxes.length; i++) {
    ...
    
    modifierCheckboxes[i].addEventListener('click', function (e) {
        bindModifierCheckboxes(e);
    });
}

function bindModifierCheckboxes(e) {
    var shortcutKeys = configuration.readSettings('shortcutKeys');
    var modifierKey = e.target.attributes['data-modifier-key'].value;

    if (shortcutKeys.indexOf(modifierKey) !== -1) {
        var shortcutKeyIndex = shortcutKeys.indexOf(modifierKey);
        shortcutKeys.splice(shortcutKeyIndex, 1);
    }
    else {
        shortcutKeys.push(modifierKey);
    }

    configuration.saveSettings('shortcutKeys', shortcutKeys);
    ipc.send('set-global-shortcuts');
}

我們遍歷了所有的復選框,綁定click事件,在每次點擊時判斷是否含有變更鍵。然后根據結果,修改數組,保存結果到設置,再給主進程發(fā)送消息,它會更新我們的全局快捷鍵。

下面要在main.js里的設置「set-global-shortcuts」這個ipc通道來更新我們的全局快捷鍵:

ipc.on('set-global-shortcuts', function () {
    setGlobalShortcuts();
});

很簡單,像這樣,我們的全局快捷鍵就配置好了!


菜單上有什么?

切換到名為06-shortcuts-configurable的tag:
git checkout 06-shortcuts-configurable

對桌面應用來說,另一個重要的概念就是菜單欄。分為上下文菜單(右擊菜單),托盤菜單(綁定到托盤圖標),應用菜單(在OS X上)等多種。

在本指南中,我們將添加一個綁定菜單的托盤圖標。我們也會利用這次機會探索另一種進程間通信--remote模塊。

remote模塊實現從渲染進程向主進程發(fā)送RPC式調用。你引入模塊,在渲染進程操作,方法在主進程被初始化,你調用的方法都在主進程被執(zhí)行。實際中,這意味著你在index.js遠程請求原生的GUI模塊,調用它們的方法,都會在main.js中執(zhí)行。你可以在index.js里引入BrowserWindow模塊,初始化一個瀏覽器窗口。背后的原理是,異步調用新的瀏覽器窗口的主進程。


現在我們創(chuàng)建一個菜單,并把它綁定到托盤圖標,在index.js中加入下面代碼:

var remote = require('remote');
var Tray = remote.require('tray');
var Menu = remote.require('menu');
var path = require('path');

var trayIcon = null;

if (process.platform === 'darwin') {
    trayIcon = new Tray(path.join(__dirname, 'img/tray-iconTemplate.png'));
}
else {
    trayIcon = new Tray(path.join(__dirname, 'img/tray-icon-alt.png'));
}

var trayMenuTemplate = [
    {
        label: 'Sound machine',
        enabled: false
    },
    {
        label: 'Settings',
        click: function () {
            ipc.send('open-settings-window');
        }
    },
    {
        label: 'Quit',
        click: function () {
            ipc.send('close-main-window');
        }
    }
];
var trayMenu = Menu.buildFromTemplate(trayMenuTemplate);
trayIcon.setContextMenu(trayMenu);

原生的GUI模塊(菜單和托盤)的方法會被遠程調用,是很安全的。

把圖標定義成托盤圖標。OS X支持圖像模板(依照慣例,圖像的文件名以「Template」結尾,可以被當做一個模板圖像),這讓使用深淺色主題變得很容易。其他系統(tǒng)用常規(guī)的圖標。

在Electron中有很多種方法創(chuàng)建菜單。我們的方法是創(chuàng)建一個菜單模板(一個包含菜單項的簡單數組),用那個模板創(chuàng)建菜單。最后,綁定新的菜單到托盤圖標。


打包你的應用

切換到名為07-ready-for-packaging的tag:
git checkout 07-ready-for-packaging

如果不能讓人們下載使用,這樣的應用有什么意義?


用「electron-packager」為所有系統(tǒng)打包你的應用很簡單。簡單來說,「electron-packager」幫你完成所有用Electron打包你應用的工作,最終生成你要發(fā)布的平臺的安裝包。

它可以作為CLI應用或構建過程的一部分,更復雜的構建情況不在本文所涉及范圍內,但我們如果能用打包腳本,會使打包更簡單。用「electron-packager」比較麻煩,打包應用的基本命令是:

electron-packager <location of project> <name of project> <platform> <architecture> <electron version> <optional options>

其中,

  • location of project是你項目文件夾的位置,
  • name of project定義你的項目名,
  • platform決定要構建的平臺(*all* 包括Windows,Mac和Linux ),
  • architecture決定構建哪個構架下(x86或x64,all表示兩者),
  • electron version讓你選擇要用的Electron版本

第一次打包用時比較久,因為要下載平臺的二進制文件,隨后的打包將會快的多。

我(在Mac系統(tǒng))打包發(fā)聲器應用的命令是:

electron-packager ~/Projects/sound-machine SoundMachine --all --version=0.30.2 --out=~/Desktop --overwrite --icon=~/Projects/sound-machine/app/img/app-icon.icns

命令的選項理解起來都比較簡單。為了獲得精美的圖標,你首先要找一款類似這個軟件可以把PNG文件轉換到這些格式的工具,把它轉換成.icns格式(Mac用)或者.ico格式(Window用)。如果在非Windows系統(tǒng)給Windows平臺的應用打包,你需要安裝wine(Mac用戶用brew,Linux用戶用apt-get)。

每次都打這么長的命令很不方便,可以在package.json中加另一個腳本。首先,把electron-packager作為開發(fā)依賴安裝:

npm install --save-dev electron-packager

現在我們可以在package.json中添加腳本:

"scripts": {
  "start": "electron .",
  "package": "electron-packager ./ SoundMachine --all --out ~/Desktop/SoundMachine --version 0.30.2 --overwrite --icon=./app/img/app-icon.icns"
}

在命令行里執(zhí)行下面的命令:

npm run-script package

這個打包命令會啟動electron-packager,在當前目錄下找到目標應用文件,打包,保存到桌面。如果你用的是Windows系統(tǒng),需要修改腳本,不過改動很小。

當前狀態(tài)的發(fā)聲器,最后打包后大小高達100MB。別擔心,可以把它壓縮到不到一半的容量。

如果你想要更進一步,可以嘗試electron-builder,它用electron-packager生成的打包好的文件,可以生成自動安裝包。


可以添加的其他功能

應用已經打包好,準備就緒。你也可以添加自己想要的功能。

這是一些想法:

  • 可以顯示應用的快捷鍵,作者等信息的幫助界面,
  • 加一個綁定菜單的圖標入口可以打開信息界面,
  • 為了更快的編譯和分發(fā),編寫打包的腳本,
  • node-notifier加入通知功能,推送用戶正播放的是什么聲音,
  • 用lodash得到更整潔的代碼,
  • 打包應用前,將你所有的CSS和JavaScript文件用構建工具壓縮,
  • 檢查應用是否有新版本,用服務器調用之前介紹的node-notifier并通知客戶

挑戰(zhàn)來了--嘗試抽取出發(fā)聲器瀏覽器窗口的邏輯,用這些邏輯在瀏覽器中創(chuàng)建web頁面,實現相同的發(fā)聲器。一個代碼庫--兩個產品(桌面應用和web應用),超棒!


深入Electron

我們只接觸到了Electron比較淺顯知識。實際上,實現如查看主機電源選項或在界面上顯示多種信息都很簡單。這些功能已經內建好,請查閱Electronde API文檔。

Electron的API文檔只是Electron在Github上資料庫的一小部分,其他文件夾也值得一看。

Sindre Sorhus正在維護超酷的Electron資源列表,你可以在列表中找到很多很酷的項目,也有Electron應用構架方面很好的總結,可以學習之后重構我們的代碼。

最后,Electron是基于io.js(將合并回Node.js)的,兼容絕大部分的Node.js模塊,可以用來擴展你的應用,查看來獲取你需要的信息。


這就完了?

當然不是。

現在是時候來創(chuàng)建更復雜的應用了。在本指南中,我沒有選擇用更多函數庫和構建工具,只強調了重要的概念。你也可以用ES6或Typescript來寫你的應用,使用Angular或React框架,用gulp或Grunt來簡化你的構建過程。

為什么不用你最喜歡的語言,框架和構建工具,配合Flickr API,node-flickrapi創(chuàng)建一個Flickr桌面同步應用呢?或者用Google官方的Node.js函數庫創(chuàng)建一個Gmail客戶端?

選一個吸引你的想法,創(chuàng)建一個資料庫,開始做吧。

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多