1. 程式人生 > >【Electron Playground】Electron 視窗問題彙總

【Electron Playground】Electron 視窗問題彙總

> 作者:[Kurosaki](https://juejin.im/user/3843548381187853) > 本節旨在彙總在開發Electron 視窗可能遇到的問題,做一個彙總,後續遇到問題會持續更新。 ### 1. 視窗閃爍問題。 ```javascript const { BrowserWindow } = require('electron'); const win = new BrowserWindow(); win.loadURL('https://github.com'); ``` 使用new BrowserWindow() 創建出視窗,如果不作任何配置的話,視窗就會出現,預設是白色的;這個時候使用win.loadURL('https://github.com'),載入遠端資源,視窗重新渲染,從而導致窗口出現閃爍。 解決方法: ```javascript const { BrowserWindow } = require('electron'); const win = new BrowserWindow({ show:false }); win.loadURL('https://github.com'); win.once('ready-to-show',()=>{ win.show(); }) ``` ### 2. 老版Window7系統下,視窗白屏問題。 > 公司業務開發的Electron應用,是給老師用的,有些老師是那種老版本Window7,並且關閉了自動更新。 解決辦法: 安裝最新版的.NET Framework 官方下載地址:[https://dotnet.microsoft.com/download/dotnet-framework](https://dotnet.microsoft.com/download/dotnet-framework) 相關issue: [https://github.com/electron/electron/issues/25186](https://github.com/electron/electron/issues/25186) ### 3. macOS下電腦關機,Electron應用阻止關機問題。 > macOS 關機會把所有的視窗關閉,如果存在 ```javascript // 視窗註冊close事件 win.on('close',(event)=>{ event.preventDefault() // 阻止視窗關閉 }) ``` 這種程式碼,會導致阻止系統關機。 ### 4. `Window`  系統下,使用 `hide()` 方法,可能導致頁面掛住不能用。 導致這種場景可以是因為呼叫 `hide()` 之後不呼叫 `show()`  方法,而只是呼叫 `restore()` 方法,會導致頁面掛住不能用。所以得在 `restore()` 方法之後新增 `show()` 方法 ### 5. 新版Electron,導致渲染程序無法訪問到remote模組。 > 切換成新版的Electron,new BrowserWindow(options)配置更新,webPreferences中配置enableRemoteModule:true ### 6. macOS下無邊框視窗,頂部拖拽問題。 > 在建立視窗時,配置一下preload.js,程式碼如下: ```javascript function initTopDrag() { const topDiv = document.createElement('div') // 建立節點 topDiv.style.position = 'fixed' // 一直在頂部 topDiv.style.top = '0' topDiv.style.left = '0' topDiv.style.height = '20px' // 頂部20px才可拖動 topDiv.style.width = '100%' // 寬度100% topDiv.style.zIndex = '9999' // 懸浮於最外層 topDiv.style.pointerEvents = 'none' // 用於點選穿透 topDiv.style['-webkit-user-select'] = 'none' // 禁止選擇文字 topDiv.style['-webkit-app-region'] = 'drag' // 拖動 document.body.appendChild(topDiv) // 新增節點 } window.addEventListener('DOMContentLoaded', function onDOMContentLoaded() { initTopDrag() }) ``` ### 7. Window系統下,隱藏選單問題。 > Window系統下,選單長的很醜,有2種方案可以隱藏選單 1. 使用無邊框視窗,去除選單和邊框,自己手寫一個控制的邊框,目前github都有這些庫; 1. 使用autoHideMenuBar:true 但是按下ALT鍵會出現選單 ### 8. 視窗之間通訊。 1. 主程序建立視窗 配置preload.js,將通訊方法掛載到window ```javascript /** * 這個是用於視窗通訊例子的preload, * preload執行順序在視窗js執行順序之前 */ import { ipcRenderer, remote } from 'electron' const { argv } = require('yargs') const { BrowserWindow } = remote // 父視窗監聽子視窗事件 ipcRenderer.on('communication-to-parent', (event, msg) => { alert(msg) }) const { parentWindowId } = argv if (parentWindowId !== 'undefined') { const parentWindow = BrowserWindow.fromId(parentWindowId as number) // 掛載到window // @ts-ignore window.send = (params: any) => { parentWindow.webContents.send('communication-to-parent', params) } } ``` 建立視窗傳入id ```javascript browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => { event.preventDefault() // 在通過BrowserWindow建立視窗 const win = new BrowserWindow({ show:false, webPreferences: { preload:preload.js, additionalArguments:[`--parentWindow=${browserWindow.id}`] // 把父視窗的id傳過去 } }); win.loadURl(url); win.once('ready-to-show',()=>{ win.show() }) }) ``` 2. 父子視窗 > 沒有上述那麼麻煩,配置preload就可以,具體實現 ```javascript import { remote, ipcRenderer } from 'electron' // 父視窗監聽子視窗事件 ipcRenderer.on('communication-to-parent', (event, msg) => { alert(msg) }) const parentWindow = remote.getCurrentWindow().getParentWindow() // @ts-ignore window.sendToParent = (params: any) => parentWindow.webContents.send('communication-to-parent', params) ``` 3. 渲染程序建立視窗 > 渲染程序通訊很簡單,通過window.open,window.open會返回一個`windowObjectReference` 通過postMessage就可以通訊了。並且window.open 支援傳preload等配置。 ### 9. 視窗全屏問題。 使用按鈕全屏和退出全屏是可以的,但是先點選左上角