Electron小白入門自學筆記(一)
碼文不易啊,轉載請帶上本文鏈接呀,感謝感謝 //www.cnblogs.com/echoyya/p/14297176.html
一、從Hello Electron開始
-
創建一個空的文件夾,並創建入口
main.js
文件,index.html
內容文件, -
安裝
electron
-
npm init -y:初始化配置文件 package.json
-
npm i electron
-
-
main.js 文件
-
引入模組,創建應用
-
創建窗口
-
載入內容
-
打開調試工具(可選)
-
關閉窗口及應用監聽
-
-
執行文件
-
直接執行: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('//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
-
創建
menu.js
,引入模板,創建菜單模板 -
構建菜單(實例化一個菜單對象)
-
設置菜單對象到應用中
-
用到的方法:
buildFromTemplate
,setApplicationMenu
-
選項:
- type:(‘normal’ | ‘separator’ | ‘submenu’ | ‘checkbox’ | ‘radio’)
- label:標題
- accelerator:快捷鍵,區分 mac 及 win
- submenu:子菜單
- click:點擊事件
-
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);
三、主進程(Main Process)和渲染進程(Render Process)
主進程
在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
模組,- 渲染進程不能直接使用 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
A. 渲染進程 給 主進程 發送指令
-
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);
})
運行結果:主進程輸出結果會列印在終端,而渲染進程輸出結果會列印在調試工具中
B. 主進程 給 渲染進程 發送指令
了解了 渲染進程 -> 主進程
後,反之就很好理解和掌握了,大同小異,簡單總結一下:
-
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) });
運行結果:
C. 渲染進程 給 渲染進程 發送指令
思路:渲染進程 -> 主進程 -> 渲染進程
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)
})
D. 不同渲染進程之間數據共享
-
可以很簡單的使用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模組是主進程可使用模組
-
調用語法:
dialog.showMessageBox({ ... })
,版本升級後不支援原來的回調方法,改為返回promise
對象 -
常用配置對象參數:
- type:類型(error/info)
- title:標題
- message:提示資訊
- icon:本地圖標(需使用nativeImage模組,且主進程與渲染進程均可用該模組)
- buttons:按鈕(數組類型)
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)
打包必要元素及格式輸入: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 "
},