Electron小白入門自學筆記(一)

Echoyya、發表於2021-01-19

碼文不易啊,轉載請帶上本文連結呀,感謝感謝 https://www.cnblogs.com/echoyya/p/14297176.html

一、從Hello Electron開始

  1. 建立一個空的資料夾,並建立入口 main.js 檔案,index.html內容檔案,

  2. 安裝electron

    • npm init -y:初始化配置檔案 package.json

    • npm i electron

  3. main.js 檔案

    • 引入模組,建立應用

    • 建立視窗

    • 載入內容

    • 開啟除錯工具(可選)

    • 關閉視窗及應用監聽

  4. 執行檔案

    • 直接執行: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

  1. 建立menu.js ,引入模板,建立選單模板

  2. 構建選單(例項化一個選單物件)

  3. 設定選單物件到應用中

  4. 用到的方法:buildFromTemplate , setApplicationMenu

  5. 選項:

    • type:('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio')
    • label:標題
    • accelerator:快捷鍵,區分 mac 及 win
    • submenu:子選單
    • click:點選事件
  6. 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環境的殼。

四、在渲染程式中建立一個子視窗

  1. 建立渲染程式對應render.js檔案

  2. 渲染程式引入BrowserWindow模組,需要藉助於remote模組,

    • 渲染程式不能直接使用 BrowserWindow ,因為該模組預設是主程式允許使用的
    • 藉助 remote ,從中引入主程式中的模組,需要在主程式視窗中配置 enableRemoteModule,允許渲染程式 呼叫主程式模組
  3. 並在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. 渲染程式 給 主程式 傳送指令

  1. ipcRenderer模組:渲染程式引入,用於傳送事件給主程式,和監聽主程式返回的回覆事件

    • const { ipcRenderer } = require('electron');

    • 傳送事件:ipcRenderer.send('事件名稱',傳遞的資料);

    • 監聽事件:ipcRenderer.on('監聽事件名稱',接收的資料);

  2. 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. 主程式 給 渲染程式 傳送指令

瞭解了 渲染程式 -> 主程式 後,反之就很好理解和掌握了,大同小異,簡單總結一下:

  1. main.js 傳送指令 兩種方式:

    ipcMain.on('myName',function(event,msg){
      // 1. 通過event 
      //event.sender.send('msg-b','程式媛');
      
      // 2. 通過webContents (推薦)
      win.webContents.send('msg-b','程式媛'); 
    })
    
  2. 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. 不同渲染程式之間資料共享

  1. 可以很簡單的使用H5的api來完成,如localStorage,sessionStorage,但今天要說的是另一種

  2. 在主程式中將一個物件儲存為全域性變數,然後通過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 模組

  1. 首先dialog模組是主程式可使用模組

  2. 呼叫語法:dialog.showMessageBox({ ... }),版本升級後不支援原來的回撥方法,改為返回promise物件

  3. 常用配置物件引數:

    • 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 "
},

相關文章