Electron

文章目录

  • 应用架构
    • 项目结构
    • 主进程和渲染进程
    • API
  • 功能
    • 通知(Notifications)
    • more...
  • 打包
    • electron-packager
    • electron-builder
  • 常见问题
    • 主进程控制台乱码

应用架构

项目结构

几乎没有结构,只需要3个文件

package.json

定义一下入口文件,启动脚本,包依赖就可以

{
  "name": "electron-demo",
  "version": "1.0.0",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "devDependencies": {
    "electron": "^8.0.0"
  }
}

main.js

// 通过 require electron 来控制程序
const { app, BrowserWindow } = require('electron')

// app加载完毕
app.on('ready', () => {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  // 加载 html 页面
  mainWindow.loadFile('index.html')

  // 打开控制台
  mainWindow.webContents.openDevTools()
})

// macOS 的一些设置
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

app.on('activate', function () {
  if (BrowserWindow.getAllWindows().length === 0) createWindow()
})

index.html

这种结构可以和任何框架(vue,ng)或普通页面结合构建桌面应用程序

主进程和渲染进程

  • 基于 Chromium 的多进程架构引擎,Electron 采用了类似的结构,一个主进程(相当于浏览器)对应多个渲染引擎(相当于多个标签)

  • 例子中运行的main.js称为主进程,创建的 BrowserWindow 实例称为渲染进程

API

通过 require('electron') 来使用 Electron 提供的 API,有些 API 仅供渲染进程使用或仅供主进程使用,也有一些 API 两类进程都可使用

在渲染进程中创建BrowserWindow实例

BrowserWindow 对象只能在主进程中使用,为了在渲染进程中也可以创建新实例,可以与主进程通信来执行任务

Electron通过 remote 模块暴露了一些在主进程中才能使用的 API

// 渲染进程无法通过此方式使用 BrowserWindow 对象
// const { BrowserWindow } = require('electron')

const { remote } = require('electron')
// 使用 remote 暴露的 API
const { BrowserWindow } = remote

new BrowserWindow({
	/* ... */
})

使用node.js API

Electron 可以使用所有的 node.js API,可以和底层交互了哇

譬如 fs

const fs = require("fs");

document.getElementById("save").onclick = () => {
    let writerStream = fs.createWriteStream("test.txt");  //Write输入流

    writerStream.write("hello","UTF-8");

    writerStream.on("finish",function(chunk){
        /* ... */
    })
    
    writerStream.on("err",function(err){
        console.log(err.stack);
    })
}

功能

通知(Notifications)

渲染进程可以使用h5新增的 HTML5 Notification API,主进程可以使用 Electron 的 Notifications 模块,两者体验类似,但仍有细微差异

主进程

const { Notification } = require('electron')

// 创建一条通知
let notification = new Notification({
  title: '标题',
  body: '正文'
})

// 事件处理
// show 事件
notification.on('show', () => {
  console.log("通知显示")
})

// close 事件
// 这个事件不能保证在所有情况下都会触发,譬如使用 close 方法或单击导致的关闭不会触发
notification.on('close', () => {
  console.log("通知关闭")
})

// click 事件
notification.on('click', () => {
  console.log("通知被单击")
})

// 当前系统是否支持桌面通知
if(Notification.isSupported()){
  notification.show()  // 立即显示
  setTimeout(() => {
    notification.close()  // 延时关闭
  }, 5000)
}

详细的通知参数和事件见 官方API文档

渲染进程

注:此 API 属 h5 新特性,不仅仅针对 Electron

// 浏览器是否支持此特性
if(! window.Notification){
    console.log("浏览器不支持 Notification 特性")
}
// 是否有通知权限
else if(Notification.permission === 'granted'){
    let notification = new Notification('标题', {
        body: '正文',
        icon: 'favicon.ico'
    })

	// new 后自动弹出,无需手动显示

	setTimeout(() => {
    	notification.close()  // 手动关闭
    }, 2000)

	// 事件处理
	// click 事件
    notification.onclick = () => {
        console.log("通知被单击")
    }
	// show 事件
    notification.onshow = () => {
        console.log("通知显示")
    }
	// error 事件
    notification.onerror = () => {
        console.log("错误")
    }
	// close 事件
	// 和主进程 Electron 的 Notification 对象相比,这个事件保证在多数情况下都会触发
    notification.onclose = () => {
        console.log("通知被关闭")
    }
}
// 请求权限
else if (Notification.permission !== 'denied') {
    Notification.requestPermission(permission => {
        // 如果用户同意,就可以向他们发送通知
        if (permission === "granted") {
            let notification = new Notification("Hi there!");
        }
    });
}

WIN10渲染进程通知被拦截无法显示

开发环境下,通常默认通知可以显示,手动禁止后,因为通知管理无对应应用程序,所以无法恢复禁止,需要在主进程加入:

app.setAppUserModelId(process.execPath)

然后将 node_modules\electron\dist\electron.exe 固定到开始屏幕,即可恢复显示,若再次禁止,可以更换文件夹再次尝试

win10.v1909 测试只需要加入 app.set... 语句即可恢复显示

more…

官方DOC

打包

electron-packager

安装

npm install electron-packager --save-dev

打包命令

electron-packager   --platform= --arch= [--out= --icon= optional flags...]
arg details
sourcedir 项目路径
appname 应用名
platform 平台
arch 架构
outdir 输出路径
icon 图标

可以添加到脚本中方便打包,例子:

"packager": "electron-packager ./ testApp --platform=win32 --arch=ia32 --out=./outApp --icon=./favicon.ico"

解决资源被墙无法打包

可以使用淘宝仓库

npm config set ELECTRON_MIRROR http://npm.taobao.org/mirrors/electron/

或者在 package.json 配置

"build": {
    "electronDownload": {
      "mirror": "https://npm.taobao.org/mirrors/electron/"
    }
}

使用时发现它是去 源/vx.x.x/ 下载,淘宝镜像格式是 源/x.x.x/,所以只能手动下载它需要的资源,然后放在自己的服务器(或本地?),设为自己的源再打包

譬如使用 v8.0.0 版本的 Electron,按上面的脚本,会下载

  • 源/v8.0.0/electron-v8.0.0-win32-ia32.zip
  • 源/v8.0.0/SHASUMS256.txt

两个文件,将这两个文件部署到自己的仓库就可以进行打包了

electron-packager 仅在首次打包时下载资源,以后打包断网什么的都随意

electron-builder

安装

npm install electron-builder --save-dev

打包命令

"scripts": {
	"electron-builder": "electron-builder --win --x64",  // 生成绿色版 + 安装包 + 绿色版压缩包
	"electron-builder-dir": "electron-builder --dir --win --x64"  // 仅生成绿色版
},
"build": {
    "appId": "com.demo.app",
    "mac": {
      "target": ["dmg","zip"]
    },
    "win": {
      "target": ["nsis","zip"]
    },
    "directories": {
      "output": "builder"  // 指定打包内容存放路径
    },
    "files": [  // 指定要打包的资源
      "dist/**/*",  // html 项目资源
      "main.js"  // electron 入口文件
    ]
}

解决资源被墙无法打包

首次打包会下载必要的资源,资源是国外源,很容易超时导致失败,需手动下载(慢慢等总会下载完的)或下载,得到需要的资源

Electron_第1张图片

C:\Users\username\AppData\Local\electron-builder\Cache

如果只需要打包为绿色版就不需要下载 nsis 和 nsis-resources 了

常见问题

主进程控制台乱码

修改 package.jsonstart 脚本

"start": "electron .""start": "chcp 65001 && electron ."

你可能感兴趣的:(Electron)