Electron官方示例
$ git clone https://github.com/electron/electron-quick-start
$ cd electron-quick-start
$ npm i
$ npm start
在VSCode调试项目
打包、分发
创建一个electron项目
- 初始化项目文件夹。填写一些列 信息。
 
npm init
- 安装
electron到开发依赖 
npm install --save--dev electron
- 修改package.json文件
 
"scripts": {
    "start":"electron ."
}
- 启动
 
npm start
报错,没有需要运行的应用
创建入口文件和页面
创建主进程
在项目根目录创建main.js后,再次启动,项目不会报错,但是没有任何反应。
创建页面
在项目根目录创建index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Electron</title>
</head>
<body>
    The first Electron project;
</body>
</html>
引入页面
需要使用两个Electron的模块:app、BrowserWindow
app模块,控制应用程序的事件生命周期。BrowserWindow模块,创建和管理应用程序的 窗口。
可以在main.js中引入这两个模块,可以使用CommonJS方式
const { app, BrowserWindow } = require('electron')
然后添加一个方法,来将index.html加载进一个新的BrowserWindow实例
const createWindow = ()=>{
    const win = new BrowserWindow({
        width:800,
        height:600
    })
    win.loadFile('index.html')
}
在Electron中,只有app模块的ready事件被激活后才可以创建窗口,可以使用app.whenReady()API来监听此事件,在成功后调用createWindow()
app.whenReady().then(()=>{
    createWindow()
})
此时,再次使用npm start应该可以正常启动项目。
Ctrl + Shift + I 打开开发者工具面板
窗口生命周期
在关闭所有的窗口时,应用程序也会退出。使用app.on监听window-all-closed,在回调中处理。
app.on("window-all-closed", () => {
    if (process.platform !== "darwin") {
        app.quit()
    }
})
某些系统在关闭所有窗口时,会打开新的窗口,由于不能在ready之前创建窗口,所以在ready回调中处理该方法
app.whenReady().then(() => {
    createWindow()
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) {
            createWindow()
        }
    })
})
生命周期事件
ready:app 初始化完成。生命周期优先级:1dom-ready:一个窗口的文本加载完成。生命周期优先级:2win.webContents.on('dom-ready',()=>{})did-finsh-load:导航完成触发。生命周期优先级:3window-all-closed:所有窗口都被关闭时before-quit:在关闭窗口之前时触发will-quit:当窗口关闭并且应用退出时触发quit:当所有窗口关闭时触发 以上三个退出方法,如果指定了window-all-closed时是不会触发的,需要主动在监听window-all-closed方法的回调中去调用app.quit()才会触发。closed:当窗口关闭时触发const createWindow = ()=>{ const win = new BrowserWindow({ width:800, height:600 }) win.loadFile('index.html') win.on('close',()=>{ win = null;// 当窗口被关闭,释放内存 }) }
修改代码时自动重载
可以点击窗口上的reload刷新。
使用nodemon
"scripts": { "start":"nodemon --watch main.js --exec npm run build", "build":"electron . },
首屏白屏现象
窗口加载完成后,是没有内容的,所以有可能在短时间内是白屏,解决方法是:
const createWindow = () => {
    const win = new BrowserWindow({
        show:false,//先让窗口不显示
        width: 800,
        height: 600
    })
    // 先加载页面资源
    win.loadFile('index.html')
    // 监听窗口是否准备好显示方法
    win.on('ready-to-show',()=>{
        win.show();// 再让窗口显示
    })
}
窗口的配置
const win = new BrowserWindow({
    show:false,
    x:500,
    y:400,
    width: 800,
    height: 600,
    maxHeight:1000, // 最大高度
    maxWidth:1000,  // 最大宽度
    minHeight:100,  // 最小高度
    minWidth:100,   // 最小宽度
    resizable:false, // 是否允许修改宽高
    title:"Erickiku",// 前提是html文件没有设置title值
    icon:"favicon.ico",	// 设置图标
    //frame:false,	// 消除标题栏和菜单栏
    frame:true,
    autoHideMenuBar:true,// 这两个为true时,只隐藏菜单栏,显示标题栏
})
*打开新窗口
需要去官方文档看
自定义窗口
如果把frame设置为false,则会让标题和菜单栏都消失,可以自己自定义标题栏和最小最大化、关闭按钮等样式,但是会有无法拖动窗口和按钮没有功能,所以需要自己自定义方法,来处理这些事件。
暴露全局对象/变量
可以在预加载脚本中,向渲染器进程中的脚本暴露对象或变量,暴露的对象是全局的。
首先创建一个preload.js文件
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('versions', {
    node: () => process.versions.node,
    chrome: () => process.versions.chrome,
    electron: () => process.versions.electron,
    age: '1'
})
上文是获取了一些版本号
将脚本放在BrowserWindow的webPreferences.preload中,以让渲染进程使用。
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })
  win.loadFile('index.html')
}
现在可以在渲染器进程使用了
创建renderer.js文件
const infoHtml = document.getElementById("info")
infoHtml.innerText = `当前正在使用Chrome(v${versions.chrome()})、Node(v${versions.node()})、Electron(v${versions.electron()})`
在Html页面中引入js文件
<body>
    The first Electron project;reload
    <h1 id="info"></h1>
    <script src='./renderer.js'></script>
</body>
可以在页面上看到显示的版本号,或者是一个变量。
进程间通信
在预加载脚本中引入ipcRenderer模块,它可以使用ipcRenderer.invoke(函数名)来触发主进程中的某个函数
preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('versions', {
  pingFun: () => ipcRenderer.invoke('ping')
  // 除函数之外,我们也可以暴露变量
})
在主进程中设计监听器,监听被invoke所调用的函数
引入ipcMain模块,使用ipcMain.handle(函数名,回调函数)来监听某个函数的触发
main.js
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })
  win.loadFile('index.html')
}
app.whenReady().then(() => {
  ipcMain.handle('ping', () => 'pong')
  createWindow()
})
之后可以在渲染器进程中调用versions.pingFun,去触发主进程的回调,返回一个pong字符串
与Vue3搭配
创建项目
先创建一个vue3+vite项目
再安装electron
$ npm i electron -D
再package.json文件中,修改以下,并在项目根目录新建main.js
....
"main": "main.js",
"scripts": {
    "dev": "vite",
    "build": "vite build",
    "start": "electron .",
    "preview": "vite preview"
},
