原文連結:Electron入門教程
Electron是由Github開發,用HTML,CSS和JavaScript來構建跨平臺桌面應用程式的一個開源庫。 Electron通過將 Chromium 和 Node.js合併到同一個執行時環境中,並將其打包為Mac,Windows和Linux系統下的應用來實現這一目的。
相信大部分前端同學都聽說或者瞭解過NodeJs 它是一個基於Chrome V8 引擎的JavaScript執行時, 而 Chromium 是Google為發展自家瀏覽器Chrome而開啟的開源瀏覽器專案,可以看成是是Chrome的先行版。大家較為熟悉的VS Code 和 Atom就是使用Electron來完成的。
從開發的角度來看, Electron application 本質上是一個 Node. js 應用程式。可以讓前端開發者讓你使用純 JavaScript 呼叫豐富的原生作業系統APIs來創造桌面應用~
Quick Start
確認你的網路可以訪問github , 若訪問受限參考 安裝指南 來了解如何用代理、映象和自定義快取
你肯定已經已經安裝好git和node了,那麼只要:
# 官網已經有 electron-quick-start 倉庫克隆下來
git clone https://github.com/electron/electron-quick-start
# 進入資料夾
cd electron-quick-start
# 安裝依賴包並執行
npm install && npm start
複製程式碼
然後你的第一個桌面應用就開啟了!
若你跟著一起實踐到這裡,肯定會發現介面有些許不同?我這裡多了個除錯介面,那麼來看下程式碼看看。在Electron中main.js是入口檔案:
//main.js
const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win
function createWindow () {
// 建立瀏覽器視窗。
win = new BrowserWindow({ width: 800, height: 600 })
// 然後載入應用的 index.html。對應的index.html 就是初始介面。
win.loadFile('index.html')
// 開啟開發者工具
win.webContents.openDevTools()
//關於win 視窗的生命週期我們之後再研究……
// 當 window 被關閉,這個事件會被觸發。
win.on('closed', () => {
// 取消引用 window 物件,如果你的應用支援多視窗的話,
// 通常會把多個 window 物件存放在一個陣列裡面,
// 與此同時,你應該刪除相應的元素。
win = null
})
}
//關於 app 主程式的生命週期我們之後再研究……
// 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 (win === null) {
createWindow()
}
})
// 在這個檔案中,你可以續寫應用剩下主程式程式碼。
// 也可以拆分成幾個檔案,然後用 require 匯入。
複製程式碼
與現有React工程結合
迫於不會Vue ,在這裡介紹下React工程如何和Electron結合起來。
偷懶就直接使用 create-react-app 來建立react工程:
#若已安裝 請忽略
npm install -g create-react-app
create-react-app react-electron
cd react-electron
npm start
複製程式碼
新增 Electron 配置並啟動
一、 安裝 Electron包
# 在 react-electron 目錄下安裝 Electron 包
npm install -save electron
複製程式碼
二、 新增main.js
在 react-electron 目錄下新增main.js ,直接使用上面 main.js的內容 ,然後
//win.loadFile('index.html') 這一行替換為:
win.loadFile('http://localhost:3000/')
複製程式碼
這樣就將入口介面指定到react的初始介面了。
三、 啟動Electron!
修改 package.json ,新增 main homepage欄位,並新增electron-start命令:
"main": "main.js",
"homepage":".",
"scripts": {
"start": "react-scripts start",
"build": "react-scriptsbuild",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"electron": "electron ."
},
}
複製程式碼
啟動 Electron:
# 啟動react專案
npm start
# 啟動electron
npm run electron
複製程式碼
看到一篇 文章 CREATE AN APP WITH ELECTRON AND REACT 寫create-react-app和Electron結合的不錯,大家也可以參考這個。
四、在react中使用electron
直接在react中使用import electron會產生問題 issues/7300,可以寫成這種形式:
const electron = window.require('electron');
const fs = electron.remote.require('fs');
const ipcRenderer = electron.ipcRenderer;
複製程式碼
主程式和渲染程式
Electron 與web應用的區別不是很大,在原web應用的基礎上新增主執行緒互動程式碼後,甚至可以將一個線上web應用迅速的包裝成為一個客戶端應用! Electron並且內整合了 Nodejs,Nodejs 在主程式和渲染程式中都可以使用,這為我們提供了npm成千上萬的模組。
所以個人感覺應用Electron的重要在於理解主程式和渲染程式,和程式間的互動。其他API可以自己花點時間閱讀文件。
執行Electron入口檔案的程式(也就是上文執行main.js的程式)被稱為主程式,它控制著整個 App 的生命週期,從開啟到關閉。 它也管理著系統原生元素比如選單,選單欄,Dock 欄,托盤等。 主程式負責建立 APP 的每個渲染程式。而且整個 Node API 都整合在裡面;
而在主程式建立的一個個web頁面(對應上文中的win視窗)也都執行著自己的程式,即渲染程式,渲染程式各自獨立,各自擁有自己的生命週期。與主程式不同的是,它能夠同時存在多個而且執行在不一樣的程式。而且它們也能夠被隱藏。在通常的瀏覽器內,網頁通常執行在一個沙盒的環境擋住並且不能夠使用原生的資源。 然而 Electron 的使用者在 Node.js 的 API 支援下可以在頁面中和作業系統進行一些低階別的互動。
程式間通訊
Electron提供了幾種通訊方式:
一 使用ipc-renderer 和 ipc-main :
ipc-renderer 和 ipc-main 非同步互動:
//在渲染程式中:
const {ipcRenderer} = require('electron')
//傳送asynchronous-message事件到主程式
ipcRenderer.send('asynchronous-message', 'ping')
//接收主程式的asynchronous-reply通知
ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log('asynchronous-reply : args:',arg)
const message = `Asynchronous message reply: ${arg}`
document.getElementById('async-reply').innerHTML = message
})
//在主程式中:
const {ipcMain} = require('electron')
//接收渲染程式的asynchronous-message通知
ipcMain.on('asynchronous-message', (event, arg) => {
//傳送asynchronous-reply事件到渲染程式
event.sender.send('asynchronous-reply', {'ping':'pong','num':'1'})
})
複製程式碼
ipc-renderer 和 ipc-main 同步互動:
//在渲染程式中:
const {ipcRenderer} = require('electron')
const syncMsgBtn = document.getElementById('sync-msg')
syncMsgBtn.addEventListener('click', () => {
const reply = ipcRenderer.sendSync('synchronous-message', 'ping')
const message = `Synchronous message reply: ${reply}`
document.getElementById('sync-reply').innerHTML = message
})
//在主程式中:
const {ipcMain} = require('electron')
ipcMain.on('synchronous-message', (event, arg) => {
event.returnValue = 'pong'
})
複製程式碼
二 在渲染程式使用remote模組
// 在渲染程式開啟提示對話方塊
const {dialog} = require('electron').remote
dialog.showMessageBox(options, (index) => {
....
})
複製程式碼
三 在主程式向渲染程式webContents傳送訊息
win.webContents.send('ping', 'whoooooooh!')
複製程式碼
四 渲染程式之間的通訊
在兩個網頁(渲染程式)間共享資料最簡單的方法是使用瀏覽器中已經實現的 HTML5 API。 其中比較好的方案是用 Storage API, localStorage,sessionStorage 或者 IndexedDB。
你還可以用 Electron 內的 IPC 機制實現。將資料存在主程式的某個全域性變數中,然後在多個渲染程式中使用 remote 模組來訪問它。
// 在主程式中
global.sharedObject = {
someProperty: 'default value'
}
// 在第一個頁面中
require('electron').remote.getGlobal('sharedObject').someProperty = 'new value'
// 在第二個頁面中
console.log(require('electron').remote.getGlobal('sharedObject').someProperty)
複製程式碼