碼文不易啊,轉載請帶上本文連結呀,感謝感謝 https://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('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
-
建立
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 "
},