建立一個空的文件夾,並建立入口 main.js
文件,index.html
內容文件,html
安裝electron
前端
npm init -y:初始化配置文件 package.jsonnode
npm i electronweb
main.js 文件shell
引入模塊,建立應用npm
建立窗口json
加載內容windows
打開調試工具(可選)api
關閉窗口及應用監聽數組
執行文件
直接執行:electron main.js
默認執行:electron .
package.json 添加執行腳本: "start": "electorn main.js", 執行:npm run start
執行上述命令報錯解決:先可嘗試全局安裝,在執行命令,如若仍然報錯,可能須要配置腳本執行權限
windows下運行*.ps1
腳本(powershell的腳本)的時候,須要設置執行權限,PowerShell默認的執行策略就是Restricted
,禁止任何腳本的執行。
首先管理員身份運行 windows powershell ,輸入Get-ExecutionPolicy
,用於得到當前的執行策略。
Set-ExecutionPolicy
命令設置/更改執行策略,選擇RemoteSigned
這個執行策略,這個策略既安全又能夠執行本地編寫的腳本
// main.js 引入模塊 // app模塊:控制應用的生命週期 // BrowserWindow模塊: 建立瀏覽器窗口 const { app ,BrowserWindow} = require('electron'); // path模塊: node 的內置模塊,用於拼接路徑 const path = require('path'); // 1.初始化應用以後,會觸發監聽ready 事件 app.on('ready',ny_createWindow) let win; // 建立窗口 function ny_createWindow(){ // 1.1建立窗口 win = new BrowserWindow({ width:330, height:355, resizable:false, // 是否可改變寬高,默認true movable:false, // 是否可拖拽,默認true webPreferences: { nodeIntegration: true, // 是否集成 Nodejs enableRemoteModule: true, // 是否容許渲染進程 調用主進程模塊 } // 1.爲了在渲染進程中使用require(),還須要啓用 nodeIntegration 。 // 2.從v9版本開始,remote除非將 enableRemoteModule 設置爲true,不然不容許在渲染進程中使用。 }); // 1.2 加載內容 // win.loadURL('http://www.baidu.com') // 遠程 // __dirname: 當前js文件所在的文件夾路徑,絕對路徑 // win.loadURL(path.join(__dirname, './index.html')) // 本地 相對路徑 // mac 系統:須要拼接 file 協議 // path.join('file://',__dirname,'./index.html') // 1.3 調試工具 win.webContents.openDevTools(); // webContents: 控制和渲染頁面的 // 1.4 關閉窗口, 關閉窗口前想作的事 win.on('close',function(){ win = null; // 關閉窗口 app.quit(); // 關閉應用 })
建立menu.js
,引入模板,建立菜單模板
構建菜單(實例化一個菜單對象)
設置菜單對象到應用中
用到的方法:buildFromTemplate
, setApplicationMenu
選項:
main.js中引用: require('./menu');
// menu.js 引入模板 const { Menu } = require('electron') // 1.設置一個模板 let template = [ { label:'文件', submenu:[ { label:'新建文件', accelerator:'ctrl+N', click:function(){ console.log('new file') } }, { type:'separator' }, { label:'新建窗口', accelerator:(function(){ if(process.platform =='darwin'){ //mac 基於darwin return 'alt+command+M' }else{ //win return 'alt+ctrl+M' } })(), click:function(){ console.log('new window') } }, { type:'separator' }, { label:'自動保存', accelerator:'ctrl+S', type:'checkbox', checked:true, click:function(){ console.log('saved') } }, ] }, { label:'編輯' }, ] // 2. 構建菜單(實例化一個菜單對象) const menu = Menu.buildFromTemplate(template); //3. 設置菜單對象到應用中 Menu.setApplicationMenu(menu);
在Electron中,入口是一個js文件,運行這個入口文件的進程稱做主進程。
(一般會是package.json
裏的main腳本,通常是main.js)
在主進程使用BrowserWindow
模塊能夠建立並管理web頁面,也就是應用的GUI(圖形界面)
const { BrowserWindow } = require('electron'); const path = require('path'); // 主進程建立web頁面 let win = new BrowserWindow({...}); // 加載本地文件 // win.loadURL(path.join('file://',__dirname, './index.html')) // mac win.loadURL(path.join(__dirname, './index.html'))
在主進程建立的每個web頁面也都運行着本身的進程,頁面引入的js文件就屬於渲染進程。
渲染進程各自管理本身的頁面,能夠想象是瀏覽器的一個個的tab。
electron核心能夠分紅2個部分,主進程
和渲染進程
。主進程鏈接着操做系統和渲染進程,能夠看作頁面和計算機溝通的橋樑。渲染進程就是咱們所熟悉前端環境了。只是載體改變了,從瀏覽器變成了window。傳統的web環境咱們是不能對用戶的系統進行操做的。而electron至關於node環境,能夠在項目裏使用全部的node api 。
簡單理解:
給web項目套上一個node環境的殼。
建立渲染進程對應render.js
文件
渲染進程引入BrowserWindow
模塊,須要藉助於remote
模塊,
enableRemoteModule
,容許渲染進程 調用主進程模塊並在index.html
中引入render.js
,兩種引入方法及區別
<!-- 1.引入render.js --> <script src="./render-process/render.js"></script> <!-- 2.electron 基於node --> <script> require('./render-process/render.js'); </script> <-- 區別: src: 是全局變量 require: 引入的文件的最外層的變量,不是全局變量,注:爲了在渲染進程中使用require(),還需在主進程窗口配置中啓用 nodeIntegration 。 //main.js win = new BrowserWindow({ width:330, height:355, resizable:false, // 是否可改變寬高,默認true movable:false, // 是否可拖拽,默認true webPreferences: { nodeIntegration: true, // 是否集成 Nodejs enableRemoteModule: true, // 是否容許渲染進程 調用主進程模塊 } }) 使用: 1.元素綁定onclick事件 ==== src引入 2.require ==== 給元素綁定一個ID ,在render.js獲取元素並綁定事件 -->
在electron下,主進程與渲染進程相互通訊要經過ipc(Inter-Process Communication),進程間通信模塊
來完成,
主進程與渲染進程調用的ipc模塊是不同的:
主進程調用ipcMain
渲染進程調用ipcRenderer
ipcRenderer
模塊:渲染進程引入,用於發送事件給主進程,和監聽主進程返回的回覆事件
const { ipcRenderer } = require('electron')
;
發送事件:ipcRenderer.send('事件名稱',傳遞的數據)
;
監聽事件:ipcRenderer.on('監聽事件名稱',接收的數據)
;
ipcMain
模塊:主進程引入,用於接收渲染進程發送的事件並進行回覆
const { ipcMain } = require('electron')
;
監聽事件:ipcMain.on('監聽事件名稱',接收的數據)
;
index.html:
<h1>Hello Electron!</h1> <button onclick="ny_click()">click me</button> <!-- 引入render.js 渲染進程--> <script src="./render-process/render.js"></script>
render.js:
function ny_click(){ console.log('Render:','Echoyya') ipcRenderer.send('myName','Echoyya'); }
main.js:
ipcMain.on('myName',function(event,msg){ console.log('Main:',msg); })
運行結果:主進程輸出結果會打印在終端,而渲染進程輸出結果會打印在調試工具中
瞭解了 渲染進程 -> 主進程
後,反之就很好理解和掌握了,大同小異,簡單總結一下:
main.js 發送指令 兩種方式:
ipcMain.on('myName',function(event,msg){ // 1. 經過event //event.sender.send('msg-b','程序媛'); // 2. 經過webContents (推薦) win.webContents.send('msg-b','程序媛'); })
render.js 渲染進程接收指定
ipcRenderer.on('msg-b',function (event, msg) { console.log('Render:',msg) });
運行結果:
思路:渲染進程 -> 主進程 -> 渲染進程
a.js: ipcRenderer.send('dataToMain','
渲染進程 -> 主進程 -> 渲染進程')
main.js:
ipcMain.on('dataToMain',function(event,data){ win.webContents.send('dataToRender',data); })
b.js:
ipcRenderer.on('dataToRender', function (event, data) { console.log(data) })
能夠很簡單的使用H5的api來完成,如localStorage,sessionStorage,但今天要說的是另外一種
在主進程中將一個對象儲存爲全局變量,而後經過remote
模塊操做
a.js
, b.js
,並在index.html
中引入index.html:
<button id="btn1">改變數據</button> <button id="btn2">獲取數據</button> <script> require('./render-process/a.js'); require('./render-process/b.js'); </script>
main.js:
// 全局變量 global.shareObject = { name:'上海' }
a.js:
const remote = require('electron').remote; let btn1 = document.getElementById('btn1'); btn1.onclick = function(){ remote.getGlobal('shareObject').name = '北京'; console.log('has changed'); }
b.js:
const remote = require('electron').remote; let btn2 = document.getElementById('btn2'); btn2.onclick = function(){ let msg = remote.getGlobal('shareObject').name console.log(msg) }
首先dialog模塊是主進程可以使用模塊
調用語法:dialog.showMessageBox({ ... })
,版本升級後不支持原來的回調方法,改成返回promise
對象
經常使用配置對象參數:
const { dialog ,nativeImage} = require('electron'); const path = require('path'); // 1.信息對話框 dialog.showMessageBox({ title:'舒適提示', message:'XXXXX XXXXX XXXXX XXXXX XXXXX', buttons:['Yes','No'], icon:nativeImage.createFromPath(path.join(__dirname,'../src/img/icon1.png')) }).then(function(index){ if(index.response == 0){ // 點擊了Yes按鈕 console.log('I want you !'); }else{ // 點擊了No按鈕 console.log('no no no'); } }); // 2.錯誤提示框 dialog.showErrorBox('1213','訪問錯誤')
打包必要元素及格式輸入:electron-packager <應用目錄> <應用名稱> <打包平臺> --out=<輸出目錄> <架構> <應用版本> <忽略文件> <圖標> --overwrite
執行上述命令,可在輸出目錄中,打包成功一個exe 可執行文件,此命令區分mac及win,設備緣由,此處僅演示win系統打包,mac系統的同窗,需自行查找相關資料!!!
package.json:
"scripts": { "start": "electorn main.js", "pack":"electron-packager ./ test --platform=win32 --out=./dist --arch=x64 --app-version=1.0.0 --ignore=node_modules --icon=./src/img/hrbb.ico --overwrite " },