五、Electron 19

1、什么是 Electron

参见 PPT。

2、Electron 初探

2.1 常见的桌面GUI工具介绍

名称

语音

优点

缺点

QT

C++

跨平台、性能好、生态好

依赖多,程序包大

PyQT

Python

底层集成度高、易上手

授权问题

WPF

C#

类库丰富、扩展灵活

只支持Windows,程序包大

WinForm

C#

性能好,组件丰富,易上手

只支持Windows,UI差

Swing

Java

基于AWT,组件丰富

性能差,UI一般

NW.js

JS

跨平台性好,界面美观

底层交互差、性能差,包大

Electron

JS

相比NW发展更好

底层交互差、性能差,包大

CEF

C++

性能好,灵活集成,UI美观

占用资源多,包大

  • 底层依赖 + 调用:CEF、QT、Swing
  • UI美观:Electron(NW.js)、PyQT
  • 跨平台:Swing(JAVA)、PyQT(Python、C++)、Electron(前端)

技术是为业务服务的,选择合适的最重要!

2.2 桌面端设计与开发要点

1、UX/UI设计概念

**UX设计:**UX(User Experience)即用户体验,其核心是用户,体验指用户在使用产品以及与产品发生交互时出现的主观感受和需求满足。

UI设计:UI(User Interface)使用者界面,可以说是 UX 设计的一部分,其中重要的图形化或者可视化部分,都是由 UI 设计来完成的。

2、核心原则

简单易用。

3、通用原则

交互简单:上手就会,一看就懂

风格统一:菜单、导航、按钮反馈、颜色、预知提示

认知一致:名词、友好提示、划分信息、突出展示

4、桌面端设计

保持与PC端统一的风格设计与交互设计。

加入定制的菜单与专业操控设计。

减少资源加载。

2.3 初始化项目 + 项目依赖介绍

1、Electron 官网

https://www.electronjs.org/

2、初始化一个项目

felixlu electron $ npm init -y
npm i electron -D

3、配置启动脚本

在 package.json 里配置 npm 脚本:

{
  "scripts": {
    "start": "electron ."
  },
}

4、创建入口文件

  • 在项目根目录下创建文件 index.html:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Electron Demo</title>
</head>
<body>
  hello Electron
</body>
</html>
  • 在项目根目录下创建 index.js 文件,这是程序的入口文件:
const { app } = require('electron')

// 主进程
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

app.whenReady().then(createWindow)

3、Electron 核心概念

3.1 Electron 主进程与渲染进程

**主进程:**启动项目时运行的 main.js 脚本就是我们说的主进程。在主进程运行的脚本可以以创建 Web 页面的形式展示 GUI。主进程只有一个

**渲染进程:**每个 Electron 的页面都在运行着自己的进程,这样的进程称之为渲染进程(基于Chromium的多进程结构)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AJGUKNht-1667203192497)(./images/image-20220622220437989.png)]

主进程使用 BrowserWindow 创建实例,主进程销毁后,对应的渲染进程回被终止。主进程与渲染进程通过 IPC 方式(事件驱动)进行通信。

3.2 主进程事件生命周期

main process modules/app/event:https://www.electronjs.org/zh/docs/latest/api/app

app.on('window-all-closed', () => {
  console.log('window-all-closed')
  // 对于 MacOS 系统 -> 关闭窗口时,不会直接推出应用
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('quit', () => {
  console.log('quit')
})

app.whenReady().then(() => {
  createWindow()
  // 在MacOS下,当全部窗口关闭,点击 dock 图标,窗口再次打开。
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

3.3 渲染进程如何使用 Node 模块

1、通过 webPreferences/nodeIntegration

const win = new BrowserWindow({
  width: 800,
  height: 400,
  webPreferences: {
  	nodeIntegration: true,
  	contextIsolation: false
  }
})
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Electron Demo</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <h1>
    hello Electron
  </h1>
  <div id="root">
    <p>electronVersion: {{electronVersion}}</p>
    <p>nodeVersion: {{nodeVersion}}</p>
    <p>chromeVersion: {{chromeVersion}}</p>
  </div>
  <script>
    // const path = require('path')
    // console.log(path)
    const app = Vue.createApp({
      data() {
        return {
          electronVersion: process.versions.electron,
          nodeVersion: process.versions.node,
          chromeVersion: process.versions.chrome
        }
      }
    })
    app.mount('#root')
  </script>
</body>
</html>

2、通过 webPreferences/preload 实现

const win = new BrowserWindow({
    width: 800,
    height: 400,
    webPreferences: {
      // 在启动应用时在渲染进程里预加载 js
      preload: path.join(__dirname, './preload-js/index.js')
    }
  })
// preload-js/index.js

// const { contextBridge } = require('electron')
// contextBridge.exposeInMainWorld('myAPI', {
//  desktop: true
// })

const { createApp } = require('vue')
window.addEventListener('load', () => {
  const app = createApp({
    data() {
      return {
        electronVersion: process.versions.electron,
        nodeVersion: process.versions.node,
        chromeVersion: process.versions.chrome
      }
    }
  })
  app.mount('#root')
})