[electron playground series] window

Time:2021-5-3

Author:Kurosaki

This article mainly explainsElectronWindowsAPIAnd some problems encountered in the development.

Official documentsAlthough more comprehensive, but in order to develop a commercial level of desktop applications must be on the wholeElectron API  Have a deeper understanding, in order to respond to various needs.

1. Create a window

adoptBrowserWindowCome onestablishperhapsAdministrationNew browser window, each browser window has a process to manage.

1.1. Simple window creation

const { BrowserWindow } = require('electron');
const win = new BrowserWindow();
win.loadURL('https://github.com');

The results are as follows

open-windows.gif

1.1.2. Optimization

problemelectron OfBrowserWindow When a module is created, if it is not configuredshow:falseIt will be displayed when it is created, and the default background is white; Then the window requestsHTML, visual flicker will appear.

solve

const { BrowserWindow } = require('electron');
const win = new BrowserWindow({ show:false });

win.loadURL('https://github.com');

win.on('ready-to-show',()=>{
    win.show();
})

There is a big difference between the two
window-shows.gif

1.2. Management window

The so-called management window is equivalent to how many windows the main process can intervene in.

  • Routing jump of windows
  • Window opens a new window
  • Window size, position, etc
  • Display of windows
  • Window type (borderless window, parent-child window)
  • In the windowJavaScript  Ofnode  Permissions, preload scripts, etc
  • ….

All of these methods exist inBrowserWindowModule.

1.2.1. Manage windows created by applications

BrowserWindowWhen the module creates a window, it returns theWindow instanceThese * * window instances * * have many function methods, we use these methods to manage and control this window.

Use hereMapObject to store theseWindow instance

const BrowserWindowsMap = new Map()
let mainWindowId: number;

const browserWindows = new BrowserWindow({ show:false })
browserWindows.loadURL('https://github.com')
browserWindows.once('ready-to-show', () => {
  browserWindows.show()
})
BrowserWindowsMap.set(browserWindow.id, browserWindow)
Mainwindowid = browserwindow. ID // records the current window as the main window

The window is closedYou have toMapInstance deletion in.

browserWindow.on('closed', () => {
  BrowserWindowsMap?.delete(browserWindowID)
})

1.2.2. Manage user created windows

The main process can control many behaviors of the window, which will be listed one by one in the following article; The following is an example of the behavior of the main process control window to create a new window.

usenew-windowListen for new window creation

//Create window monitor
browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
  /** @params {string} disposition
  *New window: call window.open
  *  background-tab: command+click
  *Foreground tab: right click the new tag to open or click the a tag target_ Blank Open
  * /
})

Note: AboutdispositionField explanation, stepElectronic documentElectronic source codeChrome source code

extendnew-window

After experiments, not all new windows are created,new-window  You can catch it.

Windows opened in the following ways can benew-windowEvent capture

window.open('https://github.com')
link

**
Used in the rendering processBrowserWindowCreate a new window that will not be changednew-windowEvent capture
**

const { BrowserWindow } = require('electron').remote
const win = new BrowserWindow()
win.loadURL('https://github.com')

_ Rendering process access__remote_ _, The main process needs to be configured with enableremotem odule:true _
You can also open a new window in this way, but the new window of the main process cannot be captured.

applicationnew-window
new-window  It controls the creation of new windows. We can do many things with this; For example, link verification, browser open link and so on. The default browser open link code is as follows:

import { shell } from 'electron'
function openExternal(url: string) {
  const HTTP_REGEXP = /^https?:\/\//
  //Non HTTP protocol is not opened to prevent security problems caused by custom protocol
  if (!HTTP_REGEXP) {
    return false
  }
  try {
    await shell.openExternal(url, options)
    return true
  } catch (error) {
    console.error('open external error: ', error)
    return false
  }
}
//Create window monitor
browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
  if (disposition === 'foreground-tab') {
      //Prevent mouse from clicking on links
      event.preventDefault()
      openExternal(url)
  }
})

_ About__shell_ Module, you can view the official websitehttps://www.electronjs.org/docs/api/shell
_

1.3. Close the window

**close** ** Events and****closed** event
close  Event is triggered before the window is about to close, but atDOM  Ofbeforeunload  and  unload  Event.

//Window registration close event
win.on('close',(event)=>{
	Event. Preventdefault() // prevent windows from closing
})

closed  Event is triggered after the window is closed, but the window has been closed and cannot be passedevent.preventDefault()  To prevent the window from closing.

win.on('closed', handler)

The main process can close the windowAPI  There are many, but each has its own advantages and disadvantages.

1.3.1. win.close()

About thisAPI  Advantages and disadvantages of

  1. If the current window instance is registered and blockedcloseEvent, the page will not be closed, but thePrevent computer shutdown(it must be forced to exit manually);
  2. Turn off page services, such aswebsocketNext time you open a window, the page in the window willRe render
  3. Through thisAPITriggeredcloseWhat happenedunloadandbeforeunloadBefore triggering, through this point can be achievedPop up window triggered when closing

window-close.gif
The complete code is in GitHub:electron-playground

  1. Will beclosedEvent capture.

1.3.2. win.destroy()

  1. Forced exitcloseEvent (i.e. unable to passevent.preventDefault()To stop it;
  2. Close the page and the service in the page. The next time you open the window, the page in the window will be rendered again;
  3. Will beclosedEvent capture.

1.3.3. win.hide()

This is a hidden window.

  1. Hide window, triggerhideandblurEvents can also be passed through theevent.preventDefault()To stop it
  2. Just hide the window throughwin.show(), can show the window, and will maintain the original window, the service inside will not hang up

2. Hide and restore the main window

2.1. Main window

2.1.1. Whymain window?

There are many windows in an application, and one window is needed as a windowmain windowIf the window is closed, it means that the whole application is closed.
Scenario: when the application has only one page, the user clicks the close button to hide the whole application instead of closing it;
For example: other apps, such as wechat, QQ and other desktop.

Use the above method to close the windowAPI , We can hide and restore a main window.

Transform itclose  event

Let mainwindowid: number // used to mark the main window ID

const browserWindow = new BrowserWindow()

//Record the main window ID
if (!mainWindowId) {
  mainWindowId = browserWindow.id
}

browserWindow.on('close', event => {
  //If the main window is closed, block
  if (browserWindow.id === mainWindowId) {
    event.preventDefault()
    browserWindow.hide()
  }
})

2.1.2. Restore the main window display

If you can hide it, you can recover it.

const mainWindow = BrowserWindowsMap.get(mainWindowId)
if (mainWindow) {
  mainWindow.restore()
  mainWindow.show()
}

**mainWindow.show()** method: the function, as it is called, is “show window”.
_ Why, if so__mainWindow.restore()_ 
_windows_ _ If__hide_ _ Do not call after__show_ _ Method, but only calls the__restore_ Method will cause the page to hang

2.1.3. Force close main window

In some scenarios, you may need to force the exit, and attach the code:

const mainWindow = BrowserWindowsMap.get(mainWindowId)
if (mainWindow) {
  mainWindowId = -1
  mainWindow.close()
}

Existing problems

We have changedElectron  Given the behavior of the window, there will be problems in many scenarios

Problem 1: because it’s stoppedclose  Event, resulting inShut downCan’t close onmain window, you can use the following code

app.on('before-quit', () => {
    closeMainWindow()
})

On Mac OS Linux WindowsAny time.

Question 2: to avoid startingMultiple applications

app.on('second-instance', () => {
  const mainWindow = BrowserWindowsMap.get(mainWindowId)
  if (mainWindow) {
    mainWindow.restore()
    mainWindow.show()
  }
})

On Mac OS Linux WindowsAny time

Question 3: start the application for the first time, try to run the application or clickapplication programOfDocking stationorTaskbar Icon Reactivate it when

app.on('activate', () => {
  if (mainWindow) {
    mainWindow.restore()
    mainWindow.show()
  }
})

Mac OS onlylower

Question 4:Double click the tray iconopenAPP

tray.on('double-click', () => {
  if (mainWindow) {
    mainWindow.restore()
    mainWindow.show()
  }
})

In this way, the code of each link can be realized. Please refer tolink

3. Focusing and defocusing of the window

3.1. Focus

3.1.1. Configure when creating a window

const { BrowserWindow } = require('electron');
const win = new BrowserWindow();
win.loadURL('https://github.com')

focusable:true  The window can be focused, and you can use the focusedAPI 
focusable:falsestayWindowsSet infocusable: falseIt also means that it’s setskipTaskbar: true. inLinuxSet infocusable: falseWhen the window stops andwmInteractive, and the window will always be at the top;

The situation discussed below is onlyfocusable:trueIn this case

const { BrowserWindow } = require('electron');
const win = new BrowserWindow() //  focusable:true  Is the default configuration

It’s a listAPI

3.1.2. API about focus

API function
BrowserWindow.getFocusedWindow() To get the focused window
win.isFocused() Judge whether the window is focused or not
win.on('focus',handler) To monitor whether the window is focused
win.focus() Manual focus window

3.1.3. Other API side effects related to focus:

API function
win.show() Show the window and focus on it
win.showInactive() Displays the window, but does not focus on it

3.2. Out of focus

3.2.1. About defocusingapi

API function
win.blur() Unfocus window
win.on('blur',cb) Monitor out of focus

3.2.2. OthersapiSide effects are related to defocusing

api function
win.hide() Hides the window and triggers a defocus event

4. Window type

4.1. Borderless window

4.1.1. Description

Borderless window is a window without shell (including window border, toolbar, etc.) and only contains Web content

4.1.2. Implementation

Windows macOS Linux

const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600, frame: false })
win.show()

staymacOSNext, there are different ways to achieve it, officialfile

4.1.3. macOSUnique borderless

  • to configuretitleBarStyle: 'hidden'

Returns a full-size content window with hidden title bar. There are still standard window control buttons (commonly known as “traffic lights”) in the upper left corner

//Create a borderless window
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ titleBarStyle: 'hidden' })
win.show()

The results are as follows
window-type-frame.gif

  • to configuretitleBarStyle: 'hiddenInset'

Returns another window with a hidden title bar, in which the distance from the control button to the window border is greater.

//Create a borderless window
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
win.show()

The results are as follows
window-type-frame2.gif

to configuretitleBarStyle: 'customButtonsOnHover'

The results are as follows
window-type-frame3.gif

4.1.4. The top of the window cannot be dragged

Although no border window, very beautiful, you can customize the title; But changing the default behavior at the top of the electron window, we need to use code to be compatible with it and realize its original function.

window-type1.gif
This is because by default, borderless Windows cannot be dragged. The application needs toCSSSpecified in-webkit-app-region: dragLet me tell youElectronWhich areas are draggable (such as the standard title bar of the operating system) and can be used inside the draggable area-webkit-app-region: no-dragThen some of them can be excluded. Note that only rectangular shapes are currently supported.Complete documentation

use-webkit-app-region: dragTo achieve drag and drop, but will lead to internalclickThe event is invalid. This is the time when you will needclickSet element to-webkit-app-region: no-drag. Specific detailsElectron  Ofissues

In order not to affect the business code in the window, the code dragged here should bepreloadTrigger.

preload  Code running, before window code running

Core code:

//Insert a removable DOM at the top
function initTopDrag() {
  Const topdiv = document. CreateElement ('div ') // create node
  Topdiv. Style. Position ='fixed '// always at the top
  topDiv.style.top = '0'
  topDiv.style.left = '0'
  Topdiv. Style. Height ='20px '// the top 20px can be dragged
  Topdiv. Style. Width ='100% '// width 100%
  Topdiv.style.zindex ='9999 '// suspended in the outermost layer
  Topdiv. Style. Pointerevents ='none '// used for click through
  // @ts-ignore
  Topdiv. Style ['- WebKit user select'] ='none '// text selection prohibited
  // @ts-ignore
  Topdiv. Style ['- WebKit app region'] ='drag '// drag
  Document. Body. AppendChild (topdiv) // add node
}

window.addEventListener('DOMContentLoaded', function onDOMContentLoaded() {
    initTopDrag()
})

Reference when creating a windowpreload  that will do

const path = require('path')
const { BrowserWindow } = require('electron')

const BaseWebPreferences = {
  nodeIntegration: true,
  preload: path.resolve(__ Dirname, '. / windowtype. JS') // here, the preload. JS path is referenced
}

//Main window code
const win = new BrowserWindow({ webPreferences: BaseWebPreferences, frame: false, titleBarStyle: 'hiddenInset' })
win.loadURL('https://github.com')

You can drag the top of the window
window-type.gif
_ Tips: if the window is open__devtools_ , windows can also be dragged, but the drag experience is not good

4.2. Parent child window

The so-called parent-child window means that the child window is always above the parent window. As long as the child window exists, even if it is not above the parent window, the parent window cannot be operated

window-type2.gif

const { BrowserWindow } = require('electron')

let top = new BrowserWindow()
let child = new BrowserWindow({ parent: top })
child.show()
top.show()

stayCommunication between windowsThe chapter introduces the communication between parent and child windows; adoptgetParentWindow  Get the parent windowClass browserwindowproxy, bywin.postMessage(message,targetOrigin)  Realize communication

4.3. Modal window

Modal window is also a kind of parent-child window, but the display will be different

const { BrowserWindow } = require('electron')

let top = new BrowserWindow()
let child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
  child.show()
})

window-type3.gif

5. Communication between windows

To realize window communication, the business code in the window must not be affected,jdk  And so on

5.1. Main process intervention mode

The main process can intervene the rendering process to generate a new window, just when creating a window,webContentsmonitornew-window

import path from 'path'
import { PRELOAD_FILE } from 'app/config'
import { browserWindow } from 'electron';

const BaseWebPreferences: Electron.BrowserWindowConstructorOptions['webPreferences'] = {
  nodeIntegration: true,
  webSecurity: false,
  preload: path.resolve(__dirname, PRELOAD_FILE),
}


//Create window monitor
browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
    event.preventDefault()
    //Creating a window through browserwindow
    const win = new BrowserWindow({ 
      show:false, 
      webPreferences: {
        ...BaseWebPreferences,
        Additionalarguments: ['-- parentwindow = ${browserwindow. ID}'] // pass the ID of the parent window
      } 
    });
    win.loadURl(url);
    win.once('ready-to-show',()=>{
        win.show()
    })
})

staypreload.js  filewindow.process.argv, you can get the ID of the parent window,window.process.argvIs a string array, you can useyargsTo analyze

preload.js  code

import { argv } from 'yargs'
console.log(argv);

yargv-parse.png
Got the parent windowid , Encapsulate the communication code and mount it to thewindow  upper

/**
 *This is the preload for the window communication example,
 *The preload execution order is before the window JS execution order
 */
import { ipcRenderer, remote } from 'electron'
const { argv } = require('yargs')

const { BrowserWindow } = remote

//Parent window listens for child window events
ipcRenderer.on('communication-to-parent', (event, msg) => {
  alert(msg)
})

const { parentWindowId } = argv
if (parentWindowId !== 'undefined') {
  const parentWindow = BrowserWindow.fromId(parentWindowId as number)
  //Mount to window
  // @ts-ignore
  window.send = (params: any) => {
    parentWindow.webContents.send('communication-to-parent', params)
  }
}

Give it a try
window-com.gif
This method can achieve communication, but it is too cumbersome.

5.2. Parent child window communication

And main process intervention, throughipcAlmost the same way of communication, only using the parent-child window point, not throughadditionalArgumentsPass parent windowidIn the sub windowwindow.parent, you can get the parent window

browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
    event.preventDefault()
      
    //Creating a window through browserwindow
    const win = new BrowserWindow({ 
        show:false, 
        webPreferences:BaseWebPreferences,
        parent:browserWindow //  Add parent window
      });
    win.loadURl(url);
    win.once('ready-to-show',()=>{
        win.show()
    })
    
})

Disadvantages: the child window is always above the parent window.

const path = require('path')
const { BrowserWindow } = require('electron')

const BaseWebPreferences = {
  //// integrated node
  nodeIntegration: true,
  //// disable the same origin policy
  // webSecurity: false,
  //Preloaded scripts are injected through absolute addresses
  preload: path.resolve(__dirname, './communication2.js'),
}

//Main window code
const parent = new BrowserWindow({ webPreferences: BaseWebPreferences, left: 100, top: 0 })
parent.loadURL(
  'file:///' + path.resolve(__dirname, '../playground/index.html#/demo/communication-part2/main'),
)
parent.webContents.on('new-window', (event, url, frameName, disposition) => {
  //Block default events
  event.preventDefault()
  //Creating a window through browserwindow
  //Subwindow code
  const son = new BrowserWindow({
    webPreferences: BaseWebPreferences,
    parent,
    width: 400,
    height: 400,
    alwaysOnTop: false,
  })
  // son.webContents.openDevTools();
  son.loadURL(
    'file:///' +
      path.resolve(__dirname, '../playground/index.html#/demo/communication-part2/client'),
  )
})

preload.js

import { remote, ipcRenderer } from 'electron'

//Parent window listens for child window events
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)

window-com1.gif
But it has to be a father and son window, which has disadvantages.

5.3. Usewindow.open

The ultimate method

stayweb  End, usingwindow.open  Will return awindowObjectReference , It can be realized by this methodpostMessage ; But inElectron  End, endwindow.open  Methods are redefined; use  window.open  When you create a new window, a  BrowserWindowProxyObject, and provides a limited function of the sub window
MDNfileElectronfile

const  BrowserWindowProxy = window.open('https://github.com', '_blank', 'nodeIntegration=no')
BrowserWindowProxy.postMessage(message, targetOrigin)

The code is concise, and the required function is to meet the requirementsBrowserWindow(options)  inoptions  Configured, can be usedwindow.open  to configure.

6. Full screen, maximize, minimize, restore

6.1. Full screen

6.1.1. Enter full screen when creating

to configurenew BrowserWindow({ fullscreen:true })

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ fullscreen:true,fullscreenable:true })
win.loadURL('https://github.com')

6.1.2. UseAPIEnter full screen

Make sure that the current windowfullscreenable:true, belowAPITo use

  1. win.setFullScreen(flag), set the full screen status;
  2. win.setSimpleFullScreen(flag)macOSUnder the unique, simple settings, full screen.

6.1.3. Acquisition of full screen status

  1. win.fullScreenTo determine whether the current window is full screen;
  2. win.isFullScreen()macOSUnique;
  3. win.isSimpleFullScreen()macOSUnique.

6.1.4. Full screen event monitoring

  1. reziseTrigger after adjusting the window size;
  2. enter-full-screenTrigger when the window enters full screen state;
  3. leave-full-screenTriggered when the window leaves the full screen state;
  4. enter-html-full-screenIt is triggered when the window enters the full screen state triggered by HTML API;
  5. leave-html-full-screenTriggered when the window leaves the full screen state triggered by the HTML API.

6.1.5. HTML APIUnable to interact with windows

const path = require('path')
const { BrowserWindow } = require('electron')
const BaseWebPreferences = { 
    nodeIntegration: true,
    preload: path.resolve(__dirname, './fullScreen.js'), 
};
const win = new BrowserWindow({ webPreferences: BaseWebPreferences })
win.loadURL('file:///' + path.resolve(__dirname, '../playground/index.html#/demo/full-screen'))

It’s OK to use the button full screen and exit full screen, but it’s not OK to first click the full screen in the upper left corner and then use the button to exit full screen. Because we can’t know whether the current state is full screen or not.

The solution: towin.setFullScreen(flag)Method is mounted to thewindowupper
Load such a preload. JS code

import { remote } from 'electron'

const setFullScreen = remote.getCurrentWindow().setFullScreen
const isFullScreen = remote.getCurrentWindow().isFullScreen

window.setFullScreen = setFullScreen
window.isFullScreen = isFullScreen

_ Setfullscreen documenthttps://www.electronjs.org/docs/api/browser-window#winsetfullscreenflagIsfullscreen document_https://www.electronjs.org/docs/api/browser-window#winisfullscreen

6.2. Maximize and minimize

6.2.1. Create window configuration

Complete API documentation

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ minWidth:300,minHeight:300,maxWidth:500,maxHeight:500,width:600,height:600 })
win.loadURL('https://github.com')

When usingminWidth/maxWidth/minHeight/maxHeightWhen you set the minimum or maximum window size, it only limits users. It does not prevent you from passing values that do not meet the size limit to thesetBounds/setSizeorBrowserWindowThe constructor for.

6.2.2. Related events

Event name Trigger conditions
maximize Triggered when the window is maximized
unmaximize Triggered when the window exits from maximization
minimize Triggered when the window is minimized
restore Triggered when the window is restored from the minimized state

6.2.3. Related status API

  1. win.minimizableCan windows be minimized
  2. win.maximizableCan the window be maximized
  3. win.isMaximized()Is it maximized
  4. win.isMinimized()Minimize

6.2.4. Control API

  1. win.maximize()Maximize the window
  2. win.unmaximize()Exit maximization
  3. win.minimize()Minimize windows
  4. win.unminimize()Exit minimization

6.3. Window recovery

win.restore()Restores the window from the minimized state to the previous state. In the previous example, hiding and restoring the main window are also useful to this API

7. Trigger sequence of window events

window-event.png

7.1. Window loading

Browserwindow instance: that isnew BrowserWindow()  Returned instance object
Web contents: namelyBrowserWindow  In the instancewebContents  object
Webpreferences: namelynew BrowserWindow(options)  inoptions  OfwebPreferences  Configuration object

From top to bottom, in turn

environment event Trigger time
Preload of webpreferences Load the specified script in advance before running other scripts on the page. No matter whether the page is integrated with node or not, this script can access all node API. The script path is the absolute path of the file.
webContents did-start-loading This event is triggered when the spinner in the tab starts to rotate
webContents did-start-navigation This event is triggered when the window starts to navigate
In the windowJavaScript DOMContentLoaded The initial HTML document is fully loaded and parsed
In the windowJavaScript load When all page resources are loaded
BrowserWindowexample show When the window is displayed and triggered
webContents did-frame-navigate frameAt the end of navigation
webContents did-navigate main frameAt the end of navigation
BrowserWindowexample page-title-updated Triggered when document title changes
webContents page-title-updated Triggered when document title changes
webContents dom-ready This event is triggered when the text in a frame is loaded
webContents did-frame-finish-load Triggered when the framework completes navigation
webContents did-finish-load Triggered when navigation is complete, the tab’s Spinner stops rotating
webContents did-stop-loading This event is triggered when the spinner in the tab ends the rotation

7.2. After loading the window, the user triggers events (excluding reset and move)

event effect
page-title-updated Triggered when document title changes
blur Triggered when the window loses focus
focus Triggered when the window gains focus
hide Window hidden
show Window display
maximize Triggered when the window is maximized (MAC is double-click the title)
unmaximize Triggered when the window exits from maximization
enter-full-screen Triggered when the window enters the full screen state
leave-full-screen Triggered when the window leaves the full screen state
enter-html-full-screen Triggered when the window enters the full screen state triggered by the HTML API
leave-html-full-screen Triggered when the window leaves the full screen state triggered by the HTML API
always-on-top-changed Set or unset windows are always triggered when they appear at the top of other windows.
app-command window linuxalone possess

7.3. User mobile window

  1. Before moving windowwill-move
  2. Move in windowmove
  3. After movingmoved

7.4. User changes window size

  1. Before the changewill-resize
  2. After the changeresize

7.5. Window content exception events(webContentEvent)

Event name Error type
unresponsive Triggered when a web page becomes unresponsive
responsive Triggered when an unresponsive page becomes a response
did-fail-load Loading failed,Error code
did-fail-provisional-load During page loading, thewindow.stop()
did-frame-finish-load
crashed Triggered when the rendering process crashes or ends
render-process-gone Issued when the rendering process fails unexpectedly
plugin-crashed Triggered when a plug-in process crashes
certificate-error Link validation of certificate failed
preload-error preload.jsThrow an error

7.6. Window closing (including accidental closing)

  • Before closing: triggers theclose  event
  • In the windowJavaScript  implementwindow.onbeforeunload
  • In the windowJavaScript  implementwindow.onunload
  • After closing: trigger theclosed  event

Interested in electron? Please pay attention to our open source projectsElectron PlaygroundTo get you started, electron.

Every Friday, we will select some interesting articles and news to share with you, to nuggets to pay attention to our workXiaoqian weekly


We are the front-end technical team of tal.
We will often share with you the latest and coolest technical knowledge of the industry.
WelcomeZhihuNuggetsSegmentfaultCSDNBrief bookOpen source ChinaBlog GardenFocus on us.