【Electron Playground】Electron 視窗問題彙總
阿新 • • 發佈:2020-12-16
> 作者:[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. 視窗全屏問題。
使用按鈕全屏和退出全屏是可以的,但是先點選左上角