本文閱讀須要花費一點時間,若是時間緊迫者能夠閱讀開頭以及結尾總結。thanks
來咿呀快活呀html
首先咱們的選擇能夠在save在開發依賴上 npm install electron --save-dev 也能夠全局安裝electron npm install electron -g
這裏有一段文檔翻譯有意思的話
Electron 可讓你使用純 JavaScript 調用豐富的原生(操做系統) APIs 來創造桌面應用。 你能夠把它看做一個專一於桌面應用的 Node. js 的變體,而不是 Web 服務器。java
這不意味着 Electron 是綁定了 (GUI) 庫的 JavaScript。 相反,Electron 使用 web 頁面做爲它的 GUI,因此你能把它看做成一個被 JavaScript 控制的,精簡版的 Chromium 瀏覽器。awesomenode
主進程運行package.json 的main腳本被成爲主進程。運行在主進程中的腳本將以建立 web 頁面的方式顯示一個 GUI。
(這讓我想起了。之前作python 跟java時候gui主線程的感受。。。)python
Electron的web頁面運行在一個成爲渲染進程的進程中。 而且在頁面與操做系統中得到一些低級別的交互git
主進程使用BrowserWindow實例建立頁面github
每一個 BrowserWindow實例都在本身的渲染進程裏運行頁面。 web
當一個 BrowserWindow 實例被銷燬後,相應的渲染進程也會被終止。chrome
渲染進程相互獨立,主進程管理。npm
渲染進程只須要關心它們本身的頁面。json
網頁內是不能進行GUI操做的。
須要對應的渲染進程與主進程之間通訊。
一、使用HTML5 API 例如storage API、localstorage、sessionstorage或IndexedDB
二、IPC通訊( ipcRenderer 和 ipcMain)
三、RPC通訊(remote模塊)
首先編碼開始。
它管控文件與package.json相似。
主線程由main定義的入口文件建立
如下是不完整代碼。大概的。
須要完整代碼能夠查看github地址。
項目目錄大概爲 todo -- addWindow.html -- main.js -- package.json -- window.html
入口文件是咱們的main.js,它是一個應用中的中心調度。
// 能夠向使用nodejs時同樣引入模塊 // 這個也就是所謂的主進程,看起來就像是nodejs腳本 const electron = require('electron'); const url = require('url'); const path = require('path'); const {app,BrowserWindow,Menu,ipcMain} = electron; //設置環境 process.env.NODE_ENV = 'production'; let mainWindow; let addWindow; //listen for app to be ready app.on('ready',function(){ //1. 建立一個新的窗口 mainWindow = new BrowserWindow({}); //加載 html進窗口 mainWindow.loadURL(url.format({ pathname: path.join(__dirname,'window.html'), protocol: 'file:', //協議 slashes:true })); //file:/dirname/mainWindow.html //6. 大窗口關閉整個程序關閉 mainWindow.on('close',function(){ app.quit(); }) //2 .設置菜單 const mainMenu = Menu.buildFromTemplate(mainMenuTemplate); Menu.setApplicationMenu(mainMenu); }) //handle create add window function createAddWindow(){ //5. 新建窗口 addWindow = new BrowserWindow({ width: 300, height: 200, title: 'Add TODO list item' }); //load html into window addWindow.loadURL(url.format({ pathname: path.join(__dirname,'addWindow.html'), protocol: 'file:', //協議 slashes:true })); // 垃圾回收 addWindow.on('close',function(){ addWindow = null; }) } //7. 捕獲子窗口ipc item:add // IPC通訊 ipcMain.on('item:add',function(e,item){ console.log('item'); mainWindow.webContents.send('item:add',item); addWindow.close(); }); const mainMenuTemplate = [{ label: 'File', submenu: [//3. 設置子菜單 { label: 'Add Item', click(){ //4. 新建窗口 createAddWindow(); } }, { label: 'Clear Items', click(){ mainWindow.webContents.send('item:clear'); } }, { label: 'Quit', accelerator: process.platform =='darwin'? 'Commond+Q':'Ctrl+Q',//快捷鍵作os版本區分 click(){ app.quit(); } } ] }]; // if mac , add empty object to menu if(process.platform =='darwin'){ mainMenuTemplate.unshift({}); } // 區分開發環境 if(process.env.NODE_ENV !== 'production'){ // add devtools mainMenuTemplate.push({ label:'Developer tools', submenu:[ { role:'reload' }, { label: 'Toggle DevTools', accelerator: process.platform =='darwin'? 'Commond+I':'Ctrl+I',//快捷鍵作os版本區分, click(item,focusedWindow){ //區分點擊窗口 focusedWindow.toggleDevTools(); } } ] }); }
主進程設置好ipc通訊口。
監控渲染進程對應事件
<div class="container"> <form> <div> <label> Enter Item </label> <input type="text" id="item" autofocus> </div> <button class="btn waves-effect waves-light" type="submit">add Item</button> <!-- 將item發送到mainWindow --> </form> </div> const electron = require('electron'); const {ipcRenderer} = electron; const form = document.querySelector('form'); form.addEventListener('submit',function(e){ e.preventDefault(); // console.log(123); const item = document.querySelector('#item'); ipcRenderer.send('item:add',item.value); //使用ipc進行通訊 })
<nav> <div class="nav-wrapper"> <a class="brand-logo center"> TODO LIST </a> </div> </nav> <ul id="mainContainer"> </ul> <script> const electron = require('electron'); const {ipcRenderer} = electron; const ul = document.querySelector('#mainContainer'); ipcRenderer.on('item:add',function(e,item){ ul.className = 'collection'; const li = document.createElement('li'); li.className = 'collection-item'; const itemText = document.createTextNode(item); li.appendChild(itemText); // const li = '<li class="collection-item">'+item+'</li>'; ul.appendChild(li); // ul.innerHTML = ul.innerHTML+li; }) //clear items ipcRenderer.on('item:clear',function(e){ ul.innerHTML = ''; // if(ul.clildren.length == 0){ ul.className = ''; // } }) // Remove item by doubleclick ul.addEventListener('dblclick',function(e){ e.target.remove(); // console.log(ul.clildren.length); if(ul.children.length == 0){ ul.className = ''; } }) </script>
渲染進行的調試能夠經過webContent的openDevTool api打開,調試web頁面
const { BrowserWindow } = require('electron') let win = new BrowserWindow() win.webContents.openDevTools()
--inspect=[port] 監聽 V8 引擎中有關 port 的調試器協議信息 --inspect-brk=[port] 和--inspector 同樣,可是會在JavaScript 腳本的第一行暫停運行。
(感受這裏有點想傳統的debug nodejs in browser)
由於是使用chromium結合,因此咱們同時也可使用HTML5新特性在咱們渲染進程裏
例如離線通知,離線緩存等。
本文寫成較早,有些不妥之處還望諒解(2017年)
若有疑惑歡迎討論。