[前端開(kāi)發(fā)]PC桌面端-Electron學(xué)習(xí)筆記

Electron快速上手

基礎(chǔ)模板改造

git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install && npm start

腳手架工具開(kāi)發(fā)

https://github.com/electron-userland/electron-forge
npx create-electron-app electronApp
或者
yarn create electron-app electronApp
image.png

進(jìn)程調(diào)度

Electron 中, 與 GUI 相關(guān)的模塊(如 dialog, menu 等)只存在于主進(jìn)程,而不在渲染進(jìn)程中 。 為了能從渲染進(jìn)程中使用它們,需要用 ipc模塊來(lái)給主進(jìn)程發(fā)送進(jìn)程間消息。使用 remote 模 塊,可以調(diào)用主進(jìn)程對(duì)象的方法

mainWindow=new BrowserWindow({width:800,height:600,webPreferences: { 
 nodeIntegration: true,//開(kāi)啟渲染進(jìn)程中使用nodejs
 enableRemoteModule: true//
 }});
    mainWindow.loadFile(path.join(__dirname, "new_render.html"));

頂部菜單,右鍵菜單

https://www.electronjs.org/docs/api/menu-item
頂部菜單是在主進(jìn)程中運(yùn)行,所以需要在main.js調(diào)用。
右鍵菜單是在渲染進(jìn)程中運(yùn)行,所以需要在html文件中運(yùn)行。

//頂部菜單  src/ipcMain/menu.js
const { Menu } = require("electron");
var topMenu=[
    {
        label:"文件",
        submenu:[
            {
                label:"新建",
                accelerator:"ctrl+n",
                click:()=>{
                    console.log("Ctrl+N")
                }
            },
            {
                type:"separator"
            },
            {
                label:"保存"
            }
        ]
    },
    {
        label:"編輯",
        submenu:[
            {
                label:"復(fù)制",
                role:"copy",
                click:()=>{
                    console.log("copy")
                }
            }         
        ]
    }
];
var menuBuilder=Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menuBuilder);
//src/main.js
const createWindow = () => {    
    const mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences:{
            nodeIntegration:true,
            enableRemoteModule:true
        }
    });
    //在渲染進(jìn)程中開(kāi)啟調(diào)試模式
    mainWindow.webContents.openDevTools()
    mainWindow.loadFile(path.join(__dirname, "index.html"));
    //自定義頂部菜單
    require('./ipcMain/menu');
}

鼠標(biāo)右鍵菜單內(nèi)容同上,只不過(guò)需要在index.html渲染進(jìn)程中引入,且需要通過(guò)remote調(diào)用主進(jìn)程中的menu模塊

//渲染進(jìn)程
const { remote } = require("electron");
const Menu = remote.Menu;
....
window.onload = () => {
    window.addEventListener("contextmenu", (e) => {
        e.preventDefault();
      //彈出右鍵差菜單
        menuBuilder.popup({window:remote.getCurrentWindow()});
    }, false)
}

主進(jìn)程與渲染進(jìn)程間通信

Electron 主進(jìn)程和渲染進(jìn)程的通信主要用到兩個(gè)模塊:ipcMain 和 ipcRenderer

ipcMain:當(dāng)在主進(jìn)程中使用時(shí),它處理從渲染器進(jìn)程(網(wǎng)頁(yè))發(fā)送出來(lái)的異步和同步信息, 當(dāng)然也有可能從主進(jìn)程向渲染進(jìn)程發(fā)送消息。
ipcRenderer: 使用它提供的一些方法從渲染進(jìn)程 (web 頁(yè)面) 發(fā)送同步或異步的消息到主 進(jìn)程。 也可以接收主進(jìn)程回復(fù)的消息。

渲染進(jìn)程給主進(jìn)程發(fā)送異步消息:

const { ipcRenderer } = require('electron') ;
ipcRenderer.send('render2Main',{name:'steven'}); //渲染進(jìn)程發(fā)送異步消息到主進(jìn)程
ipcRenderer.on("main2render",(event,data)=>{
  console.log("主進(jìn)程響應(yīng)給渲染進(jìn)程的數(shù)據(jù)",data);
})

//主進(jìn)程監(jiān)聽(tīng)渲染進(jìn)程傳遞過(guò)來(lái)的數(shù)據(jù),并發(fā)送消息給渲染進(jìn)程
const { ipcMain } = require('electron'); 
ipcMain.on("render2Mainsg",(event,arg) => { 
console.log("渲染進(jìn)程傳遞過(guò)來(lái)的數(shù)據(jù)",arg)
event.sender.send("main2render","主進(jìn)程收到渲染進(jìn)程發(fā)的異步消息")})

渲染進(jìn)程給主進(jìn)程發(fā)送同步消息

//渲染進(jìn)程
const { ipcRenderer } = require('electron');
 const msg = ipcRenderer.sendSync('msg-a'); 
console.log(msg) 
//主進(jìn)程
 ipcMain.on('msg-a',(event)=> { event.returnValue = 'hello'; })

主進(jìn)程通知渲染進(jìn)程執(zhí)行操作

//主進(jìn)程 
BrowserWindow.getFocusedWindow().webContents.send('replay','new 111');

//渲染進(jìn)程 
const { ipcRenderer } = require('electron');
ipcRenderer.on('reply', function(event, arg) { console.log(arg);});

渲染進(jìn)程和渲染進(jìn)程之間通信

  • LocalStorage使數(shù)據(jù)兩個(gè)html頁(yè)面之間傳遞數(shù)據(jù)
  • 通過(guò) BrowserWindow 和 webContents 模塊實(shí)現(xiàn)渲染進(jìn) 程和渲染進(jìn)程的通信
    https://www.electronjs.org/docs/api/web-contents
    每個(gè)新窗口都是一個(gè)新的html頁(yè)面,都對(duì)應(yīng)一個(gè)窗口對(duì)象,可以通過(guò)下面的方式獲取每個(gè)窗口的id
const winId = BrowserWindow.getFocusedWindow().id;
let win = BrowserWindow.fromId(winId); //獲取到對(duì)應(yīng)id的BroswerWindow對(duì)象
//在index.html開(kāi)啟打開(kāi)另一個(gè)窗口的權(quán)限
let indexWinId ;
ipcMain.on("openNews",(event,data)=>{//渲染進(jìn)程發(fā)出打開(kāi)另一個(gè)窗口的事件:openNews
indexWinId  = BrowserWindow.getFocusedWindow().id;
    const newsWindow= new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences:{
            nodeIntegration:true,
            enableRemoteModule:true
        }
    });
    //在渲染進(jìn)程中開(kāi)啟調(diào)試模式
    newsWindow.webContents.openDevTools()
    newsWindow.loadFile(path.join(__dirname, "news.html"));
    //監(jiān)聽(tīng)當(dāng)前窗口加載完成的事件
    newsWindow.webContents.on('did-finish-load',(event) => { 
       newsWindow.webContents.send('msg',winId,'我是 index.html 的數(shù)據(jù)'+data);
     })
}
//主進(jìn)程通過(guò)index.html的winID給index.html渲染進(jìn)程回消息
   let mainWin = BrowserWindow.fromId(indexId);
    mainWin.webContents.send("toIndex",data)

Electron 中嵌入網(wǎng)頁(yè)

https://www.electronjs.org/docs/api/shell //打開(kāi)網(wǎng)頁(yè)
https://www.electronjs.org/docs/tutorial/web-embeds //嵌入網(wǎng)頁(yè)

var {shell}=require('electron') ;
shell.openExternal('https://github.com');

Important Note: we do not recommend you to use WebViews, as this tag undergoes dramatic architectural changes that may affect stability of your application. Consider switching to alternatives, like iframe and Electron's BrowserView, or an architecture that avoids embedded content by design.

官方建議使用iframe代替作為顯示網(wǎng)頁(yè)的容器

electron對(duì)話框

https://www.electronjs.org/docs/api/dialog

任務(wù)欄圖標(biāo)及菜單右鍵

https://www.electronjs.org/docs/api/tray

var { Menu, Tray,app,BrowserWindow } = require('electron');
var appIcon = new Tray(path.join(__dirname,'logo.png'));

const menu = Menu.buildFromTemplate( [
  { label: '設(shè)置', click: function () {} },
  { label: '退出', click: function () { //         
      BrowserWindow.getFocusedWindow()
                   .webContents()
                  .send('close-main-window'); 
             app.quit();
     } 
  } 
]);

appIcon.setToolTip('logo 鼠標(biāo)移入title');
appIcon.setContextMenu(menu);

應(yīng)用窗口

https://www.electronjs.org/docs/api/browser-window

  • 窗口關(guān)閉 :close
  • 最小化事件: 'minimize'
  • 事件: 'maximize'
const currWindow= BrowserWindow.getFocusedWindow(); 
currWindow.on('close',(e)=>{ 
     if(!currWindow.isFocused()){ 
        currWindow=null;
     }else{
        e.preventDefault(); /*阻止應(yīng)用退出*/
       currWindow.hide(); /*隱藏當(dāng)前窗口*/
     }
 })

全局快捷鍵&剪貼板

https://www.electronjs.org/docs/api/global-shortcut
https://www.electronjs.org/docs/api/clipboard
globalShortcut 模塊可以在操作系統(tǒng)中注冊(cè)/注銷全局快捷鍵, 以便可以為操作定制各種快捷鍵

隱藏工具欄和自定義窗口操作區(qū)域

var mainWindow = new BrowserWindow({ 
  height: 620, 
  useContentSize: true, 
  width: 1280 ,
  frame: false /*去掉頂部導(dǎo)航 去掉關(guān)閉按鈕 最大化最小化按鈕*/
});

mainWindow.setMenu(null)

自定義最大,最小,關(guān)閉

const { ipcMain, BrowserWindow } = require("electron");
//window-min,window-max',window-close是渲染進(jìn)程發(fā)送過(guò)來(lái)的自定義消息
ipcMain.on('window-min',function(){ mainWindow.minimize(); })//登錄窗口最大化 
ipcMain.on('window-max',function(){ if(mainWindow.isMaximized()){ mainWindow.restore(); }else{mainWindow.maximize(); } })
ipcMain.on('window-close',function(){ mainWindow.close(); })

自定義可拖拽區(qū)域

可拖拽的 css: -webkit-app-region: drag; 
不可拖拽的 css: -webkit-app-region: no-drag;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容