Electron入门笔记

news2024/10/21 17:00:27

Electron入门笔记

  • Electron
    • Electron 是什么
    • Electron流程模型
    • 创建第一个Electron项目
    • 配置自动重启
    • 主进程和渲染进程通信
    • 打包应用

Electron

Electron 是什么

  • 跨平台的桌面应用开发框架
  • 使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium和 Node.js

Electron流程模型

  • 主进程:

    • 主进程只有一个
    • 主要功能是管理渲染进程,与操作系统打交道。调用Native API 进行各种系统级的操作,并且可以跨平台
    • node环境,能使用node的各种API,使用node的各个模块进行操作,没有浏览器相关的属性,无法访问window等浏览器属性
      在这里插入图片描述
      渲染进程:
  • 渲染进程有多个

  • 主要是程序的展示的窗口

  • 浏览器环境,本质就是Chromium,能使用浏览器的各种API,无法使用node环境的API(ctrl shift i可以打开窗口的控制台,跟浏览器是一模一样的,ctrl R可以刷新页面)
    在这里插入图片描述

  • 主进程和渲染进程是可以通信的,可以是渲染进程向主进程单向通信,也可以是主进程想渲染进程通信,也可以双向通信,进程间的通信称为IPC

  • 总结:主进程(一个)管理各个渲染进程(多个),渲染进程跟主进程进行通信(渲染进程间无法直接通信,通过主进程作为中间人可以实现),主进程调用各种Native API 完成系统级操作

创建第一个Electron项目

  • 环境:需要先安装Node.js

    • 注意:先安装Node.js只是为了正确安装electron, 因为 Electron 将 Node.js 嵌入到其二进制文件中,你应用运行时的 Node.js 版本与你系统中运行的 Node.js 版本无关
  • mkdir my-electron-app && cd my-electron-app
    yarn init
    
  • 执行yarn init生成package.jsonauthordescription在打包阶段属于必填项

  • {
      "name": "electron-first",
      "version": "1.0.0",
      "main": "main.js",
      "license": "MIT",
      "author": "XiaoMing",
      "description": "Hello World",
    }
    
    
  • 安装Electron并在package.json配置启动命令

    • yarn add ELectron -D
      
    • {
        "scripts": {
          "start": "electron ." // 注意 . 不能省略
        }
      }
      
    • 启动项目前需要创建主进程,也就是package.json中对应的main,命名为main.js, 否则会报错,创建完成后,执行yarn start即可启动

    • 此时启动无报错,但也无任何反应,因为没有在主进程里配置任何东西,渲染窗口等进程需要在主进程中配置

  • 创建pages文件夹用于存放页面文件(也就是渲染进程的文件),分别创建对应的index.html,index.css,render.js文件

    • index.html中引入cssjs文件

    • htmlhead需要配置一个meta,解决CSP的警官

      • <meta
          http-equiv="Content-Security-Policy"
          content="default-src 'self'; script-src 'self' 'unsafe-inline'"
        />
        

在这里插入图片描述

      • default-src 'self'是一组配置,意思是如果不做出任何的说明,引入的外部资源,只能是属于同源
        script-src 'self' 'unsafe-inline'是另一组配置,指引入样式的时候,可以有两种写法,第一种写法
        self 是可以引入同源的样式表,第二种写法unsafe-inline 可以使用行内样式
  • <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
        <meta
          http-equiv="Content-Security-Policy"
          content="default-src 'self'; script-src 'self' 'unsafe-inline'"
        />
        <title>Hello World!</title>
        <link rel="stylesheet" href="./index.css" />
      </head>
      <body>
        <h1>Hello World!</h1>
        We are using Node.js <span id="node-version"></span>, Chromium
        <span id="chrome-version"></span>, and Electron
        <span id="electron-version"></span>.
        <script src="./render.js"></script>
      </body>
    </html>
    
    

在这里插入图片描述
需要将写好的页面加载出来,如何加载页面,这个需要主进程进行控制,因此需要配置主进程main.js

  • const { app, BrowserWindow } = require("electron");
    
    const createWindow = () => {
      const win = new BrowserWindow({
        width: 800,
        height: 600,
      });
      win.loadFile("./pages/index.html");
    };
    
    // app.whenReady().then(() => {}) 的写法与 app.on("ready", () =>{}) 同理
    
    app.on("ready", () => {
      createWindow();
      app.on("window-all-closed", () => {
        if (process.platform !== "darwin") app.quit();
      });
    });
    

在这里插入图片描述

  • 管理窗口的生命周期

    • 关闭所有窗口时退出应用 (Windows & Linux),在Windows和Linux上,关闭所有窗口通常会完全退出一个应用程序。

      // 为了实现这一点,你需要监听 app 模块的 'window-all-closed' 事件。如果用户不是在 macOS(darwin) 上运行程序,则调用 app.quit()。
      app.on('window-all-closed', () => {
        if (process.platform !== 'darwin') app.quit()
      })
      
    • 如果没有窗口打开则打开一个窗口 (macOS),macOS 应用通常即使在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。

      // 为了实现这一特性,监听 app 模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。
      // 因为窗口无法在 ready 事件前创建,你应当在你的应用初始化后仅监听 activate 事件。 通过在您现有的 whenReady() 回调中附上您的事件监听器来完成这个操作。
      
      app.on("ready", () => {
        createWindow();
      
        app.on('activate', () => {
          if (BrowserWindow.getAllWindows().length === 0) createWindow()
        })
      });
      
  • 完整项目结构
    在这里插入图片描述

  • 启动项目yarn start
    在这里插入图片描述

配置自动重启

  • 主进程每修改一次就得手动重启一次,可以配置自动重启

  • 安装nodemon

    • yarn add nodemon -D
      
  • 更改启动命令

    • {
        "scripts": {
          "start": " nodemon --exec electron ."
        },
      }
      
  • 更改完启动命令发现自动重启的是主进程,但不改主进程,只改页面,发现页面窗口是需要手动刷新的,配置一个nodemon.json即可实现页面文件也能自动刷新

    • {
        "ignore": ["node_modules", "dist"],
        "restartable": "r",
        "watch": ["*.*"],
        "ext": "html, css, js"
      }
      
      

主进程和渲染进程通信

  • 目前主进程和渲染进程是没有什么关联的,主进程只是配置了加载渲染进程,然后他们之前没有其他的关系了,此时如果需要在渲染进程里拿到主进程中的node版本号是不可行的,因为渲染进程是浏览器环境,没有process属性

  • 此时就需要一个预加载脚本作为主进程和渲染进程之间通信的桥梁,注意:预加载脚本可以拿到部分的node API,但不是所有

  • 主进程目录下创建preload.js

    • const { contextBridge } = require("electron");
      
      contextBridge.exposeInMainWorld("api", {
        version: process.version,
      });
      

在这里插入图片描述

  • 主进程需要配置运行预加载脚本

    • const createWindow = () => {
        const win = new BrowserWindow({
          width: 800,
          height: 600,
          webPreferences: {
            preload: path.resolve(__dirname, "./preload.js"),
          },
        });
        win.loadFile("./pages/index.html");
      };
      

在这里插入图片描述

  • 配置一下渲染进程的脚本

    • const nodeVersion = document.querySelector("#node-version");
      
      console.log(window);
      
      nodeVersion.textContent = api.version;
      
      
  • 最后结果
    在这里插入图片描述

  • 由此,引出,渲染进程跟主进程之间的相互通信,需要通过预加载脚本,因为预加载脚本也只能访问到node部分属性,像是文件操作等还是需要主进程来完成的

  • 完成在窗口输入内容,并写入文件,最近将文件读出来的需求即可完全理解进程间的通信
    在这里插入图片描述

  • main.js

    • const { app, BrowserWindow, ipcMain } = require("electron");
      const path = require("path");
      const fs = require("fs");
      
      const writeFile = (_, data) => {
        fs.writeFileSync(path.resolve(__dirname, "./hello.txt"), data);
      };
      
      const readFile = () => {
        return fs.readFileSync(path.resolve(__dirname, "./hello.txt")).toString();
      };
      
      const createWindow = () => {
        const win = new BrowserWindow({
          width: 800,
          height: 600,
          webPreferences: {
            preload: path.resolve(__dirname, "./preload.js"),
          },
        });
        ipcMain.on("write-file", writeFile);
        ipcMain.handle("read-file", readFile);
        win.loadFile("./pages/index.html");
      };
      
      app.on("ready", () => {
        createWindow();
      
        app.on("activate", () => {
          if (BrowserWindow.getAllWindows().length === 0) createWindow();
        });
      });
      
      app.on("window-all-closed", () => {
        if (process.platform !== "darwin") app.quit();
      });
      
      
  • preload.js

    • const { contextBridge, ipcRenderer } = require("electron");
      
      contextBridge.exposeInMainWorld("api", {
        version: process.version,
        writeFile: (data) => {
          ipcRenderer.send("write-file", data);
        },
        readFile: () => ipcRenderer.invoke("read-file"),
      });
      
      
  • render.js

    • const nodeVersion = document.querySelector("#node-version");
      const input = document.querySelector("#input");
      const write = document.querySelector("#write");
      const read = document.querySelector("#read");
      
      nodeVersion.textContent = api.version;
      
      window.onload = () => {
        write.addEventListener("click", () => {
          api.writeFile(input.value);
        });
      
        read.addEventListener("click", async () => {
          const text = await api.readFile();
          alert(text);
        });
      };
      
      
  • index.html

    • <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
          <meta
            http-equiv="Content-Security-Policy"
            content="default-src 'self'; script-src 'self' 'unsafe-inline'"
          />
          <title>Hello World!</title>
          <link rel="stylesheet" href="./index.css" />
        </head>
        <body>
          <h1>Hello World!</h1>
          We are using Node.js <span id="node-version"></span>, Chromium
          <span id="chrome-version"></span>, and Electron
          <span id="electron-version"></span>.
          <hr />
          <input id="input" />
          <button id="write">写入文件</button>
          <button id="read">读取文件</button>
          <script src="./render.js"></script>
        </body>
      </html>
      
      

在这里插入图片描述

打包应用

  • 使用 electron build 打包成一个安装包应用

  • yarn add electron-build -D
    
  • electron-build配置地址:CodeBlog/Electron/electron-builder打包详解.md at master · QDMarkMan/CodeBlog (github.com)

  • 配置package.json

    • {
        "scripts": {
          "build": "electron-builder"
        },
        "build": {
          "appId": "com.electron.myapp",
          "nsis": {
            "oneClick": false,
            "allowElevation": true,
            "allowToChangeInstallationDirectory": true
          },
          "win": {
            "icon": "./vite.svg",
            "target": [
              {
                "target": "nsis",
                "arch": [
                  "x64"
                ]
              }
            ]
          }
        }
      }
      
  • electron-builder打包慢解决方法

    • electron-builder 打包太慢解决方法build过程耗时较长,可以手动下载部分文件。镜像地址 https:/ - 掘金 (juejin.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2220168.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python网络编程】学习Socket编程,打造网络应用!

【Python网络编程】学习Socket编程&#xff0c;打造网络应用&#xff01; 网络编程是现代计算机科学中的重要一环&#xff0c;几乎所有的应用都依赖网络传输数据。无论是创建简单的客户端-服务器模型&#xff0c;还是构建复杂的网络应用&#xff0c;Socket 编程都是关键的技术…

【远程监控新体验】OpenObserve结合内网穿透无公网IP远程访问全攻略

文章目录 前言1. 安装Docker2. Docker镜像源添加方法3. 创建并启动OpenObserve容器4. 本地访问测试5. 公网访问本地部署的OpenObserve5.1 内网穿透工具安装5.2 创建公网地址6. 配置固定公网地址前言 本文主要介绍如何在Linux系统使用Docker快速本地化部署OpenObserve云原生可观…

java导出带图形的word

先看效果图&#xff1a;方法都是一样的&#xff0c;所以数据只做了前两组 第一步需要准备模版&#xff1a; 新建一个word插入图表&#xff0c;选择想要的图表。 编辑图表&#xff1a;营业额表示数字&#xff0c;季度表示文字。其他的样式编辑可根据自己的需求更改&#xff0c;…

怎么给word文字注音?准确率高达80%,操作简单

怎么给word文字注音&#xff1f;在数字化办公日益普及的今天&#xff0c;Microsoft Word作为最常用的文字处理软件之一&#xff0c;承载着无数人的文档编辑需求。然而&#xff0c;在这个看似功能强大的工具中&#xff0c;有一个实用却常被忽视的功能——为文字注音。这对于教育…

电感的学习

电感是表示电路中电流变化对电压影响的物理量&#xff0c;常用符号 LLL 表示。电感的基本公式可以从其定义和基本特性中得出&#xff0c;主要包括以下几个方面&#xff1a; 1. 电感的定义 2. 电感能量存储 3. 自感与互感 自感&#xff1a;电感器自身的电感&#xff0c;表示电…

2024 OSCAR|《开源体系建设路径模式洞察与建议》即将发布

近年来&#xff0c;开源体系建设受到高度重视&#xff0c;国家软件发展战略和“十四五”规划纲要均对开源作出重要部署&#xff0c;为我国开源体系建设和发展指明了方向。9月25日&#xff0c;工业和信息化部党组书记、部长金壮指出要加强开源体系建设&#xff0c;助推产业高质量…

03 springboot-国际化

Spring Boot 提供了很好的国际化支持&#xff0c;可以轻松地实现中英文国际化。 项目创建&#xff0c;及其springboot系列相关知识点详见&#xff1a;springboot系列 springboot系列&#xff0c;最近持续更新中&#xff0c;如需要请关注 如果你觉得我分享的内容或者我的努力对…

构建高效房屋租赁平台:SpringBoot应用案例

第1章 绪论 1.1 课题背景 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。所以各行业&#xff0c;尤其是规模较大的企业和学校等…

爱维艾夫净利润下滑权益回报率骤降,退款数量增加市占率仅1%

《港湾商业观察》施子夫 9月13日&#xff0c;爱维艾夫医院管理集团有限公司&#xff08;以下简称&#xff0c;爱维艾夫&#xff09;第二次递表港交所&#xff0c;保荐机构为中信证券。 爱维艾夫的第一次递表发生在2023年12月&#xff0c;后因递表资料失效而告终。一年不到的时…

基于SSM机场网上订票系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;机票信息管理&#xff0c;订单信息管理&#xff0c;机场广告管理&#xff0c;系统管理 前台账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;机票信息&#xf…

餐饮行业有什么好的供应链管理系统

在餐饮企业的供应链管理中&#xff0c;合适的供应链管理系统是至关重要的&#xff0c;它能够帮助企业提高食材采购效率、降低成本、确保食材供应的及时性和质量。然而&#xff0c;许多餐饮企业在供应链管理系统方面存在诸多问题&#xff0c;常常会面临以下困境&#xff1a; ●…

【路径跟踪控制:Bang-Bang 控制与车辆运动学模型】

【路径跟踪控制&#xff1a;Bang-Bang 控制与车辆运动学模型】 1. 引言2. 环境准备3. 车辆运动学模型3.1 理论基础3.2 Python 实现车辆运动学模型建模 4. Bang-Bang 控制策略4.1 理论基础4.1.1 误差角度计算与转向角调整4.1.2 Bang-Bang控制实现 4.2 完整代码4.3 控制策略解释 …

springboot051医院管理系统(论文+源码)_kaic

医院管理系统 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计算机管理医院管理系统的方案。文章介绍了医院管理系统的系统分析部分&#…

万家数科:零售业务信息化融合的探索|OceanBase案例

本文作者&#xff1a;马琳&#xff0c;万家数科数据库专家。 万家数科商业数据有限公司&#xff0c;作为华润万家旗下的信息技术企业&#xff0c;专注于零售行业&#xff0c;在为华润万家提供服务的同时&#xff0c;也积极面向市场&#xff0c;为零售商及其生态系统提供全面的核…

基于DSP+ARM+FPGA的电能质量分析仪的软件设计

软件设计是电能质量设备的核心内容&#xff0c;上述章节详细介绍了电能质量参数的 算法&#xff0c;并且通过仿真实验进行了验证&#xff0c;本章将结合现代电能质量监测设备需求实 现算法在实际电网中应用。根据设计的电能质量分析仪的需求分析&#xff0c;进行总体的 软件…

【Android】Jetpack入门知识总结(LifeCycle,ViewModel,LiveData,DataBinding等)

文章目录 LifeCycle使用Lifecycle解耦页面与组件自定义控件实现LifecycleObserver接口注册生命周期监听器 使用LifecycleService解耦Service与组件使用ProcessLifecycleOwner监听应用程序生命周期 ViewModel用法在 Fragment 中使用 ViewModel LiveDataDataBinding导入依赖基本用…

Redis 性能优化选择:Pika 的配置与使用详解

引言 在我们日常开发中 redis是我们开发业务场景中不可缺少的部分。Redis 凭借其内存存储和快速响应的特点&#xff0c;广泛应用于缓存、消息队列等各种业务场景。然而&#xff0c;随着数据量的不断增长&#xff0c;单节点的 Redis 因为内存限制和并发能力的局限&#xff0c;逐…

FP7127:降压恒流LED芯片 支持双路调色调光 PWM调光

一、降压恒流LED芯片FP7127 FP7127 是平均电流模式控制的 LED 驱动 IC&#xff0c;具有稳定输出恒流的能力&#xff0c;优秀的负载调整率与高精度的电流控制。不用额外增加外部补偿元件&#xff0c;简化 PCB 板设计。输出的LED电流精度为 2%。 如果你想进行PWM数位调光&#…

R语言机器学习教程大纲

文章目录 介绍机器学习算法监督学习Supervised Learning分类Classification回归Regression 无监督学习 Unsupervised Learning聚类 Clustering降纬 Dimensionality Reduction相关Association 强化学习Reinforcement Learning模型自由 Model-Free Methods模型驱动 Model-Based M…