electron实现桌面应用

爱被打了一巴掌 2022-11-29 13:10 424阅读 0赞

1. 简介

  • 官网
  • Electron是由GitHub开发,使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序
  • Electron 可以让你使用纯 JavaScript 调用丰富的原生 APIs 来创造桌面应用。你可以把它看作是专注于桌面应用
  • 在PC端混合app开发中,nwjs和electron都是可选的方案,它们都是基于Chromium和Node的结合体, 而electron相对而言是更好的选择方案,它的社区相对比较活跃,bug比较少,文档先对利索简洁。
  • electron 相对来说比 nw.js 靠谱。有一堆成功的案例:Atom 编辑器 2. Slack (那个独角兽公司)3. Visual Studio Code 4. WordPress 等等。。
  • Node. js 的所有 内置模块 都在Electron中可用, 第三方 node 模块中也完全支持 (包括 原生模块 )。
  • Electron 还为开发原生桌面应用程序提供了一些额外的内置模块。 某些模块仅在主进程中可用, 有些仅在渲染进程 (web 页) 中可用, 而有些在这两个进程中都可以使用。

2. 五分钟快速上手

2.1 安装electron

  • npm init
  • cnpm I electron –S
  • npx electron

2.2 配置为入口文件

  1. {
  2. "name": "electron-demo",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "main.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1",
  8. "start": "electron ."
  9. },
  10. "author": "",
  11. "license": "ISC",
  12. "dependencies": {
  13. "electron": "^8.3.0"
  14. }
  15. }

2.3 创建main.js文件

  1. const electron = require('electron')
  2. const app = electron.app
  3. app.on('ready', ()=>{
  4. new electron.BrowserWindow({
  5. width: 800,
  6. height: 300
  7. })
  8. })

2.4创建窗口

  1. app.on('ready', ()=>{
  2. const mainWindow = new BrowserWindow({
  3. width: 800,
  4. height: 500
  5. })
  6. mainWindow.loadFile('./index.html')
  7. })

3. 主进程和渲染进程

Electron 运行 package.jsonmain 脚本的进程被称为主进程。 在主进程中运行的脚本通过创建web页面来展示用户界面。 一个 Electron 应用总是有且只有一个主进程。

由于 Electron 使用了 Chromium 来展示 web 页面,所以 Chromium 的多进程架构也被使用到。 每个 Electron 中的 web 页面运行在它的叫渲染进程的进程中。

在普通的浏览器中,web页面无法访问操作系统的原生资源。 然而 Electron 的用户在 Node.js 的 API 支持下可以在页面中和操作系统进行一些底层交互。

ctrl+shift+i打开渲染进程调试

  1. app.on('ready', ()=>{
  2. const mainWindow = new BrowserWindow({
  3. width: 800,
  4. height: 500
  5. })
  6. mainWindow.loadFile('./index.html')
  7. const mainWindow2 = new BrowserWindow({
  8. width: 800,
  9. height: 500
  10. })
  11. mainWindow2.loadFile('./index2.html')
  12. })

4. 自定义原生菜单

4.1 自定义菜单

  1. const electron = require('electron')
  2. const { app, Menu } = electron
  3. const template = [
  4. {
  5. label: '文件',
  6. submenu: [
  7. {
  8. label: '新建窗口'
  9. }
  10. ]
  11. },
  12. {
  13. label: '编辑',
  14. submenu: [
  15. {
  16. label: '新建窗口'
  17. }
  18. ]
  19. }
  20. ]
  21. const menu = Menu.buildFromTemplate(template)
  22. Menu.setApplicationMenu(menu)

4.2 给菜单定义点击事件

1、点击打开新窗口

  1. submenu: [
  2. {
  3. label: '新建窗口',
  4. click: ()=>{
  5. const newMainWindow = new BrowserWindow({
  6. width: 300,
  7. height: 300
  8. })
  9. newMainWindow.loadFile('./new.html')
  10. }
  11. }
  12. ]

2、点击打开浏览器

  1. const { BrowserWindow, Menu, shell } = require('electron')
  2. const template = [
  3. {
  4. label: '文件',
  5. submenu: [
  6. {
  7. label: '文件1',
  8. click () {
  9. // 点击打开新窗口
  10. const mainWindow2 = new BrowserWindow({
  11. width: 600,
  12. height: 600
  13. })
  14. mainWindow2.loadFile('./index.html')
  15. }
  16. }
  17. ]
  18. },
  19. {
  20. label: 'csdn',
  21. click () {
  22. // 点击打开浏览器
  23. shell.openExternal('https://www.csdn.net/')
  24. }
  25. }
  26. ]

4.3 抽离菜单定义

  1. const { BrowserWindow, Menu} = require('electron')
  2. const template = [
  3. {
  4. label: '文件',
  5. submenu: [
  6. {
  7. label: '新建窗口',
  8. click: ()=>{
  9. const newMainWindow = new BrowserWindow({
  10. width: 300,
  11. height: 300
  12. })
  13. newMainWindow.loadFile('./new.html')
  14. }
  15. }
  16. ]
  17. },
  18. {
  19. label: '编辑',
  20. submenu: [
  21. {
  22. label: '新建窗口'
  23. }
  24. ]
  25. }
  26. ]
  27. const menu = Menu.buildFromTemplate(template)
  28. Menu.setApplicationMenu(menu)
  29. require('./menu')

打开调式

mainWindow.webContents.openDevTools()

4.4 自定义顶部菜单

  • 通过frame创建无边框窗口

    1. const mainWindow = new electron.BrowserWindow({
    2. frame: false
    3. })
  • 自定义窗口

    1. <div class="header" style="-webkit-app-region: drag;">
    2. </div>
  • icon

    1. const mainWindow = new electron.BrowserWindow({
    2. width: 1000,
    3. height: 600,
    4. webPreferences: {
    5. nodeIntegration: true
    6. },
    7. frame: false,
    8. icon: './hm.ico'
    9. })
  • backgroundColor

4.5 定义右键菜单

js>index.js

  1. const { remote } = require('electron')
  2. const template = [
  3. {
  4. label: '粘贴'
  5. },
  6. {
  7. label: '赋值'
  8. }
  9. ]
  10. const menu = remote.Menu.buildFromTemplate(template)
  11. window.addEventListener('contextmenu', (e) => {
  12. console.log(123)
  13. e.preventDefault()
  14. menu.popup({ window: remote.getCurrentWindow() })
  15. })

在index.html中引入

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <button>打开新的窗口</button>
  11. <script src="./js/index.js"></script>
  12. </body>
  13. </html>

能够在html中使用node方法

  1. const mainWindow = new BrowserWindow({
  2. width: 800,
  3. height: 500,
  4. webPreferences: {
  5. nodeIntegration: true
  6. }
  7. })

4.6 点页面打开浏览器

  • html

    1. <a id="a1" href="https://blog.csdn.net/weixin_41819098">打开浏览器</a>
  • js

    1. const { shell } = require('electron')
    2. const allA = document.querySelectorAll('a')
    3. allA.forEach(item => {
    4. item.onclick = function (e) {
    5. e.preventDefault()
    6. console.log(item)
    7. shell.openExternal(item.href)
    8. }
    9. })

5. 自动刷新页面

  • 安装插件

    1. cnpm install --save-dev electron-reloader
  • 在入口引入插件

    1. const reloader = require('electron-reloader')
    2. reloader(module,{ })

6. 拖拽文件进行读取

  • 定义拖拽到指定区域

    1. <div id="drop">
    2. </div>
    3. #drop {
    4. width: 300px;
    5. height: 500px;
    6. background: hotpink;
    7. }
  • 添加拖拽事件获取文件路径

    1. // 添加拖拽
    2. const dropEl = document.querySelector('#drop')
    3. dropEl.addEventListener('drop', function(e) {
    4. if(e.dataTransfer.files.length === 1) {
    5. const filePath = e.dataTransfer.files[0].path
    6. }
    7. })
    8. dropEl.addEventListener('dragover', function (e) {
    9. e.preventDefault()
    10. })
  • 引入fs模块进行读取

    1. const fs = require('fs')
    2. // 添加拖拽
    3. const dropEl = document.querySelector('#drop')
    4. dropEl.addEventListener('drop', function(e) {
    5. if(e.dataTransfer.files.length === 1) {
    6. const filePath = e.dataTransfer.files[0].path
    7. const fileContent = fs.readFileSync(filePath).toString()
    8. this.innerText = fileContent
    9. }
    10. })
    11. dropEl.addEventListener('dragover', function (e) {
    12. e.preventDefault()
    13. })

7. 打开对话框

7.1 读取文件

  • 定义点击事件

    1. <button onclick="openFile()">打开</button>
  • 定义事件函数

    1. // 打开对话框
    2. function openFile() {
    3. const res = remote.dialog.showOpenDialogSync({
    4. title: '选择文件',
    5. buttonLabel: '哈哈',
    6. filters: [
    7. { name: 'Custom File Type', extensions: ['js','html','json'] },
    8. ]
    9. })
    10. const fileContent = fs.readFileSync(res[0]).toString()
    11. dropEl.innerText = fileContent
    12. }

7.2 保存文件

  • 定义点击事件

    1. <button onclick="saveFile()">保存</button>
  • 事件函数

    1. // 保存对话框
    2. function saveFile() {
    3. const res = remote.dialog.showSaveDialogSync({
    4. title: '保存文件',
    5. buttonLabel: '保存文件',
    6. filters: [
    7. { name: 'index', extensions: ['js'] },
    8. ]
    9. })
    10. fs.writeFileSync(res, 'hahhdasdshafsdahjk')
    11. }

8. 消息提示

  • 定义事件

    1. <button onclick="messageBox()">提示</button>
  • 事件函数

    1. // 提示信息
    2. function messageBox() {
    3. remote.dialog.showMessageBoxSync({
    4. type: 'none',
    5. buttons: ['确定'],
    6. title: '提示消息',
    7. message: '明天会下雨呦'
    8. })
    9. }

9. 定义快捷键

9.1 主线程定义

  • 引入

    1. const { app, BrowserWindow, globalShortcut } = require('electron')
  • 在ready中注册快捷键

    1. const { app, BrowserWindow, globalShortcut } = require('electron')

9.2 渲染进程定义

  • 通过remote注册

    1. // 定义快捷键
    2. remote.globalShortcut.register('Ctrl+O', () => {
    3. console.log('ctrl+o')
    4. })
  • 定义快捷键最大、最小、关闭窗口

    1. globalShortcut.register('Ctrl+T',()=>{
    2. mainWindow.unmaximize();
    3. })
    4. globalShortcut.register('Ctrl+H',()=>{
    5. mainWindow.close()
    6. })
    7. globalShortcut.register('Ctrl+M',()=>{
    8. mainWindow.maximize()
    9. })

10. 渲染进程和主线程通讯

  • 定义按钮

    1. <div class="maxWindow no-drag" onclick="maxWindow()"></div>
  • 事件函数

    1. function maxWindow() {
    2. ipcRenderer.send('max-window')
    3. }
  • 主线程定义事件

    1. ipcMain.on('max-window', () => {
    2. mainWindow.maximize()
    3. })
  • 传参

    1. let windowSize = 'unmax-window'
    2. function maxWindow() {
    3. windowSize = windowSize === 'max-window' ?'unmax-window':'max-window'
    4. ipcRenderer.send('max-window',windowSize)
    5. }
  • 接收参数

    1. ipcMain.on('max-window', (event,arg) => {
    2. console.log(arg)
    3. if(arg === 'unmax-window') return mainWindow.maximize();
    4. mainWindow.unmaximize()
    5. })
  • 通过isMaximized判断当前窗口

11. 网络请求

  1. async function getMsg () {
  2. const res = await fetch('http://127.0.0.1:3006/api/person').then(res=>res.json())
  3. console.log(res)
  4. }

12 .electron结合框架开发

12.1 结合react

利用react初始化项目
  • npx create-react-app electron-react
  • cd electron-react
  • npm start
安装electron
  • cnpm i electron
  • 添加electron的任务

    1. "main": "main.js",
    2. "scripts": {
    3. "start": "react-scripts start",
    4. "build": "react-scripts build",
    5. "test": "react-scripts test",
    6. "eject": "react-scripts eject",
    7. "electron": "electron ."
    8. },
  • 添加main.js https://github.com/electron/electron-quick-start/blob/master/main.js

    1. const { app, BrowserWindow} = require('electron')
    2. function createWindow () {
    3. // Create the browser window.
    4. const mainWindow = new BrowserWindow({
    5. width: 800,
    6. height: 600
    7. })
    8. // Open the DevTools.
    9. // mainWindow.webContents.openDevTools()
    10. }
    11. app.whenReady().then(() => {
    12. createWindow()
    13. })
  • 加载react项目

    1. mainWindow.loadURL('http://localhost:3000/')

12.2 electron结合vue

同react

13 electron打包

  • 将vue项目打包
  • 修改electron引入的文件

    1. mainWindow.loadFile('./dist/index.html')
  • 安装electron-packager

    1. "packager": "electron-packager ./ HelloWorld --platform=win32 --arch=x64 --out ./outApp --overwrite --icon=./favicon.ico"

发表评论

表情:
评论列表 (有 0 条评论,424人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Electron实现桌面日历

    前言概述         本文介绍使用Electron来实现桌面日历示例,该桌面日历可切换年份和月份的数据,可显示假期的数据等不同功能;         开发环境:no